2010-02-09 6 views
1

J'ai des processus longs dans mon application, je l'ai créé un ATTENDRE S'IL VOUS PLAÎT formulaire et j'appeler sur un autre fil comme celui-ci:« WAIT » sous forme cache principale forme

public void ShowWait() 
    { 
     continueWait = true; 
     ThreadPool.QueueUserWorkItem((x) => 
      { 
       using (frmWait espera = new frmWait()) 
       { 
        espera.ShowInTaskbar = false; 
        espera.Show(); 
        while (continueWait) 
         Application.DoEvents(); 
        espera.Close(); 
       } 
      }); 
    } 

Et pour fermer le formulaire J'utilise:

public void HideWait() 
    { 
     continueWait = false; 
    } 

Il fonctionne très bien, mais j'ai un problème, lorsque le formulaire d'attente est affiché, les principales pertes forment le focus et toute autre course application (Excel, Word, etc.) en même temps va vers le haut et mon application va à l'arrière de toutes les applications. J'ai essayé d'utiliser Activate() et Focus() mais seul le cadre de la barre des tâches est activé, mais l'application reste à l'arrière de toutes les applications.

Une lumière à ce sujet?

Merci d'avance

+4

Je vous recommande fortement de remplacer votre boucle while par l'utilisation d'un waithandle (tel que 'ManualResetEvent') que vous signalez dans la méthode' HideWait'. De cette façon, vous n'utiliserez pas de ressources processeur inutiles. –

+0

Lorsque j'utilise un événement de réinitialisation manuelle ou automatique, l'application se bloque, le formulaire d'attente ne montre pas l'animation d'attente et l'application entière attend le signal. – Argons

+0

Déjà résolu ce problème ici plusieurs fois ... Jetez un oeil à: 1. http://stackoverflow.com/questions/2183520/backgroundworkers-never-stop-being-busy/2183963#2183963 2. http: // stackoverflow.com/questions/2152445/displaying-please-wait-message/2153082#2153082 – Oliver

Répondre

1

Je ne peux pas reproduire d'autres applications allant vers le haut, mais, par rapport à la suggestion de Fredrik laisser tomber la boucle while, cela fonctionne pour moi:

AutoResetEvent processing = new AutoResetEvent(false); 

private void HideWait() 
{ 
    processing.Set(); 
} 

private void ShowWait() 
{   
    ThreadPool.QueueUserWorkItem((x) => 
    { 
     using (frmWait espera = new frmWait()) 
     { 
      espera.ShowInTaskbar = false; 
      espera.Show(); 
      processing.WaitOne(); 
      espera.Close(); 
     } 
    }); 
} 

EDIT:

Pour éviter la principale forme perdre le focus:

[DllImport("user32.dll")] 
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 

static readonly int SW_SHOWNOACTIVATE = 4; 

AutoResetEvent processing = new AutoResetEvent(false); 

private void HideWait() 
{ 
    processing.Set(); 
} 

private void ShowWait() 
{ 
    ThreadPool.QueueUserWorkItem(c => 
    { 
     using (frmWait espera = new frmWait()) 
     { 
      espera.ShowInTaskbar = false; 
      ShowWindow(espera.Handle, SW_SHOWNOACTIVATE); 
      processing.WaitOne(); 
      } 
     }); 
    } 
} 
+0

Bonjour Cher, j'ai besoin d'un projet simple par exemple. pouvez-vous m'aider en envoyant ou en donnant un lien. Merci d'avance. [email protected] – Zolfaghari

0

J'espère avoir bien compris votre problème. Donc, vous voulez mettre le WaitForm toujours au top? Si oui, avez-vous défini la propriété

espera.TopMost = true; 

?

+0

Oui J'ai défini la propriété, le formulaire d'attente s'affiche correctement, le problème est avec le formulaire principal. – Argons

0

Je pense que vous voulez un formulaire modal, essayez

espera.ShowDialog(); 

OTOH Je ne comprends pas vraiment ce que vous voulez donc je peux me tromper.

+0

La forme d'attente a le TopMost = true, donc ShowDialog() n'est pas nécessaire – Argons

+0

ShowDialog pourrait être ce que vous voulez, parce que lorsque la tâche est terminée, le formulaire principal obtiendra le focus lorsque le formulaire d'attente est fermé. (Je pense) –

+0

J'ai essayé d'utiliser ShowDialog mais le formulaire d'attente va dans le coin supérieur droit et le formulaire principal n'a toujours pas le focus. – Argons

1

Votre extrait de code ne me reproche pas le problème. Ce qui compte vraiment, c'est ce qui se passe avec le formulaire principal. Ce que vous voyez n'est pas inhabituel. Lorsque votre formulaire d'attente se ferme, Windows va chercher une autre fenêtre dans votre application pour donner le focus. S'il ne peut pas en trouver un, il choisira une autre fenêtre d'un autre processus et l'amènera au premier plan. En effet, votre formulaire principal disparaîtra derrière cette fenêtre.

Cela est garanti à se produire lorsque votre formulaire principal est désactivé, peut-être que vous définissez sa propriété Enabled sur false? J'imagine que cela peut aussi arriver lorsque votre formulaire principal ne répond toujours pas aux messages Windows, cette partie est trouble.

Evitez ce genre de problèmes (et le logement de threads incorrect que vous utilisez pour le formulaire d'attente) en exécutant le code qui prend beaucoup de temps sur un thread d'arrière-plan au lieu du thread UI. BackgroundWorker a été conçu pour rendre cela facile.

1

Est-ce que vous essayez d'utiliser la surcharge de Show qui accepte une fenêtre propriétaire, et passer un référence nulle à ce sujet?J'ai connu des problèmes similaires dans le passé qui ont été résolus de cette façon:

espera.Show(null); 

Il semble y avoir une certaine différence dans le comportement de l'appel Show() (qui est mis en œuvre dans le type Control et qui définit simplement Visible = true, qui tournez le code des triggers dans le type Form dans ce cas), et appelez Show(owner).

Questions connexes