Je n'ai jamais vraiment utilisé le threading auparavant en C # où je dois avoir deux threads, ainsi que le thread principal de l'interface utilisateur. Fondamentalement, j'ai ce qui suit.
public void StartTheActions()
{
//Starting thread 1....
Thread t1 = new Thread(new ThreadStart(action1));
t1.Start();
// Now, I want for the main thread (which is calling `StartTheActions` method)
// to wait for `t1` to finish. I've created an event in `action1` for this.
// The I wish `t2` to start...
Thread t2 = new Thread(new ThreadStart(action2));
t2.Start();
}
Donc, essentiellement, ma question est de savoir comment faire attendre un fil pour qu'un autre se termine. Quelle est la meilleure façon de procéder?
c#
multithreading
Maxim Zaslavsky
la source
la source
Réponses:
Je peux voir 5 options disponibles:
1. Thread.Join
Comme pour la réponse de Mitch. Mais cela bloquera votre thread d'interface utilisateur, mais vous obtenez un délai d'expiration intégré pour vous.
2. Utilisez un
WaitHandle
ManualResetEvent
est unWaitHandle
comme jrista suggéré.Une chose à noter est que si vous souhaitez attendre plusieurs threads,
WaitHandle.WaitAll()
cela ne fonctionnera pas par défaut, car il a besoin d'un thread MTA. Vous pouvez contourner ce problème en marquant votreMain()
méthode avecMTAThread
- cependant, cela bloque votre pompe de message et n'est pas recommandé d'après ce que j'ai lu.3. Déclenchez un événement
Voir cette page de Jon Skeet sur les événements et le multi-threading, il est possible qu'un événement puisse devenir désabonné entre le
if
et leEventName(this,EventArgs.Empty)
- cela m'est déjà arrivé.(J'espère que ces compilent, je n'ai pas essayé)
4. Utilisez un délégué
Si vous utilisez la méthode _count, il peut être judicieux (pour être sûr) de l'incrémenter en utilisant
Interlocked.Increment(ref _count)
Je serais intéressé de connaître la différence entre l'utilisation de délégués et d'événements pour la notification de thread, la seule différence que je sais est que les événements sont appelés de manière synchrone.
5. Faites-le plutôt de manière asynchrone
La réponse à cette question a une description très claire de vos options avec cette méthode.
Délégué / Événements sur le mauvais fil
La façon de faire les événements / délégués signifie que votre méthode de gestionnaire d'événements est sur thread1 / thread2 et non sur le thread d'interface utilisateur principal , vous devrez donc revenir en haut des méthodes HandleThreadDone:
la source
Ajouter
après l'avoir démarré, mais cela n'accomplira pas grand-chose car c'est essentiellement le même résultat que de courir sur le thread principal!
Je peux fortement recommandé de lire le livre électronique gratuit Threading in C # de Joe Albahari , si vous souhaitez acquérir une compréhension du threading dans .NET.
la source
Join
c'est littéralement ce que le demandeur semble avoir demandé, cela peut être extrêmement mauvais en général. Un appel àJoin
raccroche le fil à partir duquel cela est fait. Si cela se trouve être le fil principal de l'interface graphique, c'est MAUVAIS ! En tant qu'utilisateur, je déteste activement les applications qui semblent fonctionner de cette façon. Alors s'il vous plaît voir toutes les autres réponses à cette question et stackoverflow.com/questions/1221374/…Les deux réponses précédentes sont excellentes et fonctionneront pour des scénarios simples. Il existe cependant d'autres moyens de synchroniser les threads. Ce qui suit fonctionnera également:
ManualResetEvent est l'un des différents WaitHandle que le framework .NET a à offrir. Ils peuvent fournir des capacités de synchronisation de threads beaucoup plus riches que les outils simples mais très courants comme lock () / Monitor, Thread.Join, etc. Ils peuvent également être utilisés pour synchroniser plus de deux threads, permettant des scénarios complexes tels qu'un thread `` maître '' qui coordonne plusieurs threads `` enfants '', plusieurs processus simultanés qui dépendent de plusieurs étapes les uns des autres à synchroniser, etc.
la source
Si vous utilisez à partir de .NET 4, cet exemple peut vous aider:
depuis: https://stackoverflow.com/a/4190969/1676736
la source
Vous voulez la
Thread.Join()
méthode ou l'une de ses surcharges .la source
Je demanderais à votre thread principal de transmettre une méthode de rappel à votre premier thread, et quand c'est fait, il invoquera la méthode de rappel sur le thread principal, qui peut lancer le deuxième thread. Cela empêche votre fil principal de se bloquer pendant qu'il attend une jointure ou un Waithandle. Passer des méthodes en tant que délégués est une chose utile à apprendre de toute façon avec C #.
la source
Essaye ça:
la source
Publier pour peut-être aider d'autres personnes, j'ai passé pas mal de temps à chercher une solution comme celle que j'avais proposée. J'ai donc adopté une approche un peu différente. Il y a une option de compteur ci-dessus, je l'ai juste appliquée un peu différemment. J'étais en train de tourner de nombreux threads et j'ai incrémenté un compteur et décrémenté un compteur au fur et à mesure qu'un thread démarrait et s'arrêtait. Ensuite, dans la méthode principale, je voulais faire une pause et attendre la fin des threads.
Documenté sur mon blog. http://www.adamthings.com/post/2012/07/11/ensure-threads-have-finished-before-method-continues-in-c/
la source
Lorsque je veux que l'interface utilisateur puisse mettre à jour son affichage en attendant la fin d'une tâche, j'utilise une boucle while qui teste IsAlive sur le thread:
la source
Voici un exemple simple qui attend qu'une bande de roulement se termine, dans la même classe. Il fait également un appel à une autre classe dans le même espace de noms. J'ai inclus les instructions "using" afin qu'il puisse s'exécuter en tant que Winform tant que vous créez button1.
la source