2010-10-06 6 views
0

après avoir lu quelques articles, je ne suis toujours pas sûr de comprendre le multi-threading pour résoudre mon problème particulier .Comment attendre le fil de travail dans le formulaire principal?

J'ai un formulaire principal qui va démarrer un thread de travail d'arrière-plan (travailleur). Le thread de travail effectuera une boucle infinie While (! Stop) et s'arrêtera à la fin de chaque itération se terminera par l'objet global Stop (objet de verrouillage en lecture seule). Avec le bon fonctionnement lorsque l'utilisateur appuie sur le bouton Stop, le travailleur s'arrête après l'itération en cours.

Maintenant, je veux que lorsque l'utilisateur ferme le formulaire principal, il va d'abord mettre le drapeau d'arrêt, laisser le travailleur finir son travail actuel. Après cela, le formulaire principal se fermera. Semble assez simple, mais je ne pouvais pas le faire fonctionner.

J'ai essayé soit worker.Join(), soit test woker.IsAlive dans une boucle while, mais les deux cas vont verrouiller l'application (Mainform) après quelques secondes pour une raison quelconque?

Ce qui suit est mon code à l'intérieur gestionnaire d'événements Form_Closing (ne fonctionne pas):

   // Tell the thread to stop the file 
       Stop(); 
       Logger.Info("Stopping the thread by Close the application"); 
       //Not working as well      
       //worker.Join(); 
       while (worker.IsAlive) 
       { 
        Thread.Sleep(5000); 
        Logger.Info("After sleep for 5 seconds"); 
       } 
       Logger.Info("worker thread stopped"); 

Une chose intéressante est que le thread de travail semble écrit toujours du journal des événements jusqu'à la fin de chaque itération de boucle, puis le reste de l'entrée de journal sera l'événement de formulaire principal à l'intérieur de la boucle while (worker.IsAlive).

Répondre

2

La jointure attendra toujours sur le thread, l'utiliser dans le thread d'interface utilisateur rendra l'application semble verrouillée. IsAlive ne bloque rien dans le thread graphique, c'est votre Thread.Sleep.

ne somethnig comme ceci:

while (worker.IsAlive) 
{ 
    Thread.sleep(50); 
    Application.DoEvents(); 
} 
+0

Merci, cette solution semble bien fonctionner. –

0

Vous créez une impasse en quelque sorte mettre un point de rupture partout où vous demandez et libérer l'objet de verrouillage. Vous pouvez également utiliser la classe system.threading.monitor pour tester si le verrou est disponible plutôt que de créer un blocage. Familiarisez-vous avec la fenêtre des discussions dans VS.

+0

Malheureusement, ceci est notre premier besoin de projet .NET 4.0 et par conséquent je travaille actuellement en utilisant VS2010 Express. Ne ressemble pas à une fenêtre de discussion pour le débogage. –

0

Gardez à l'esprit que tout code que vous utilisez qui provoque le thread d'interface utilisateur de suspendre son obligation normale des messages de pompage se manifestera comme accrocher à l'utilisateur. En d'autres termes, ne pas appeler une méthode qui peut bloquer notamment Thread.Join, Thread.Sleep, WaitHandle.WaitOne, etc.

Puisque vous voulez que le travailleur de mettre fin à la fermeture de la forme alors je suggère de laisser la forme proche après le signal d'arrêt a été envoyé au fil de travail. Ajoutez un Thread.Join appel au point d'entrée de votre application après l'appel à Application.Run. Puisque vous fermez l'application, vous pouvez appeler le Thread.Abort si le thread ne répond pas en temps opportun. Voici un exemple de code.

public void Main(string[] args) 
{ 
    var form = new YourForm(); 
    Application.Run(form); 
    if (!form.WorkerThread.Join(TIME_TO_WAIT)) 
    { 
    form.WorkerThread.Abort(); 
    } 
} 
+0

Merci Brian Gideon, j'ai testé votre solution mais ma forme principale va se fermer instantanément. Le problème est que je n'ai pas vraiment compris votre solution, pas sûr que je l'ai mis en œuvre de la bonne façon. –

+0

Fondamentalement, je viens d'appeler Stop() pour définir l'indicateur d'arrêt pour le thread de travail dans l'événement de fermeture du formulaire. Et je pense qu'à ce point mon formulaire principal sera fermé et l'exécution reviendra le programme.cs à la ligne: if (! Form.WorkerThread.Join (TIME_TO_WAIT)) mais comme le formulaire principal est fermé à ce moment, et que la fonction Logger ne fonctionne pas à partir de ce point, comment puis-je savoir ce qui s'est passé à partir de ce point? –

Questions connexes