Ich habe noch nie zuvor Threading in C # verwendet, wo ich zwei Threads sowie den Haupt-UI-Thread haben muss. Grundsätzlich habe ich folgendes.
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();
}
Meine Frage ist also im Wesentlichen, wie man einen Thread warten lässt, bis ein anderer fertig ist. Was ist der beste Weg, dies zu tun?
c#
multithreading
Maxim Zaslavsky
quelle
quelle
Antworten:
Ich kann 5 verfügbare Optionen sehen:
1. Thread.Join
Wie bei Mitch's Antwort. Dies blockiert jedoch Ihren UI-Thread, Sie erhalten jedoch ein Timeout, das für Sie integriert ist.
2. Verwenden Sie a
WaitHandle
ManualResetEvent
ist einWaitHandle
wie jrista vorgeschlagen.Wenn Sie auf mehrere Threads warten möchten,
WaitHandle.WaitAll()
funktioniert dies standardmäßig nicht, da ein MTA-Thread erforderlich ist. Sie können dies umgehen, indem Sie IhreMain()
Methode mit markieren.MTAThread
Dies blockiert jedoch Ihre Nachrichtenpumpe und wird nach dem, was ich gelesen habe, nicht empfohlen.3. Feuern Sie ein Ereignis ab
Auf dieser Seite von Jon Skeet finden Sie Informationen zu Ereignissen und Multithreading. Es ist möglich, dass ein Ereignis zwischen dem
if
und dem nicht mehr abonniert wirdEventName(this,EventArgs.Empty)
- es ist mir schon einmal passiert.(Hoffentlich kompilieren diese, ich habe es nicht versucht)
4. Verwenden Sie einen Delegaten
Wenn Sie die Methode _count verwenden, ist es möglicherweise (aus Sicherheitsgründen) eine Idee, sie mit zu erhöhen
Interlocked.Increment(ref _count)
Mich würde interessieren, welchen Unterschied es zwischen der Verwendung von Delegaten und Ereignissen für die Thread-Benachrichtigung gibt. Der einzige Unterschied, den ich kenne, besteht darin, dass Ereignisse synchron aufgerufen werden.
5. Tun Sie es stattdessen asynchron
Die Antwort auf diese Frage enthält eine sehr klare Beschreibung Ihrer Optionen mit dieser Methode.
Delegate / Events im falschen Thread
Die Veranstaltung / Delegierten Art , die Dinge werden Ihre Event - Handler bedeuten Methode ist auf thread1 / thread2 nicht die Haupt - UI - Thread , so müssen Sie direkt an der Spitze der HandleThreadDone Methoden zurückschalten:
quelle
Hinzufügen
nachdem Sie es gestartet haben, aber das wird nicht viel bewirken, da es im Wesentlichen das gleiche Ergebnis ist wie das Ausführen auf dem Haupt-Thread!
Ich kann Joe Albaharis Threading in C # -freiem E-Book nur empfehlen , wenn Sie sich mit Threading in .NET vertraut machen möchten.
quelle
Join
buchstäblich das ist, wonach der Fragesteller gefragt zu haben scheint, kann dies im Allgemeinen äußerst schlecht sein. Ein Aufruf vonJoin
legt den Thread auf, von dem aus dies ausgeführt wird. Wenn das der Haupt-GUI-Thread ist, ist dies SCHLECHT ! Als Benutzer verabscheue ich aktiv Anwendungen, die so zu funktionieren scheinen. Also bitte alle anderen Antworten auf diese Frage und stackoverflow.com/questions/1221374/…Die beiden vorherigen Antworten sind großartig und funktionieren für einfache Szenarien. Es gibt jedoch auch andere Möglichkeiten, Threads zu synchronisieren. Folgendes wird auch funktionieren:
ManualResetEvent ist eines der verschiedenen WaitHandles , die das .NET Framework bietet. Sie bieten viel umfangreichere Funktionen zur Thread-Synchronisierung als die einfachen, aber sehr verbreiteten Tools wie lock () / Monitor, Thread.Join usw. Sie können auch zum Synchronisieren von mehr als zwei Threads verwendet werden, wodurch komplexe Szenarien wie ein 'Master'-Thread ermöglicht werden das koordiniert mehrere "untergeordnete" Threads, mehrere gleichzeitige Prozesse, die von mehreren zu synchronisierenden Stufen voneinander abhängig sind, usw.
quelle
Bei Verwendung von .NET 4 kann dieses Beispiel Ihnen helfen:
von: https://stackoverflow.com/a/4190969/1676736
quelle
Sie möchten die
Thread.Join()
Methode oder eine ihrer Überladungen .quelle
Ich würde Ihren Hauptthread eine Rückrufmethode an Ihren ersten Thread übergeben lassen, und wenn dies erledigt ist, wird die Rückrufmethode auf dem Hauptthread aufgerufen, die den zweiten Thread starten kann. Dies verhindert, dass Ihr Hauptfaden hängt, während er auf einen Join oder Waithandle wartet. Das Übergeben von Methoden als Delegaten ist ohnehin eine nützliche Sache, um mit C # zu lernen.
quelle
Versuche dies:
quelle
Das Posten, um vielleicht anderen zu helfen, hat ziemlich viel Zeit damit verbracht, nach einer Lösung zu suchen, wie ich sie mir ausgedacht habe. Also habe ich einen etwas anderen Ansatz gewählt. Es gibt oben eine Zähleroption, ich habe sie nur etwas anders angewendet. Ich drehte zahlreiche Threads ab und erhöhte einen Zähler und dekrementierte einen Zähler, als ein Thread gestartet und gestoppt wurde. Dann wollte ich in der Hauptmethode pausieren und warten, bis die Threads abgeschlossen sind.
In meinem Blog dokumentiert. http://www.adamthings.com/post/2012/07/11/ensure-threads-have-finished-before-method-continues-in-c/
quelle
Wenn ich möchte, dass die Benutzeroberfläche ihre Anzeige aktualisieren kann, während sie auf den Abschluss einer Aufgabe wartet, verwende ich eine while-Schleife, die IsAlive für den Thread testet:
quelle
Hier ist ein einfaches Beispiel, das darauf wartet, dass ein Profil innerhalb derselben Klasse fertig ist. Es ruft auch eine andere Klasse im selben Namespace auf. Ich habe die "using" -Anweisungen eingefügt, damit sie als Winform ausgeführt werden können, solange Sie button1 erstellen.
quelle