Ich bin sehr neu in Threading, als Anfänger in C #. Ich habe ein Programm, das mehrere Threads innerhalb einer Windows-App abfeuern wird. Mein Ziel ist es, einen neuen Thread für jedes Element innerhalb einer Liste zu starten. Die Elemente in dieser Liste sind Workstationnamen in einem Netzwerk. Jeder Thread, der erstellt wird, sieht Reparaturen auf jedem Rechner aus, wenn der Thread fertig ist, schreibt er in eine Protokolldatei von gefundenen Fehlern usw. Aber ich möchte herausfinden können, wann alle Threads beendet sind. Also, wenn ich 100 Maschinen habe, 100 Fäden, wie ermittle ich, wenn alle geschlossen haben?
Heres meine Methode unten: -
%Vor%Der Weg dazu wäre, einen Verweis auf alle Threads zu behalten und dann Join auf ihnen. Dies bedeutet im Grunde, dass der aktuelle Thread blockiert wird, bis der verbundene Thread abgeschlossen ist.
Ändern Sie Ihre Schleife zu etwas wie:
%Vor% (wobei _machineThreads eine Liste von System.Thread
ist)
Sie können dann blockieren, bis alle mit etwas wie abgeschlossen sind:
%Vor%JEDOCH - das wollen Sie fast sicher nicht für das von Ihnen beschriebene Szenario tun:
Warten Sie niemals in einem GUI-Ereignishandler auf die Beendigung des Threads oder irgendetwas anderes. Wenn Sie viele Threads spawnen (und ja, tun Sie das nicht - siehe Robs Post) oder viele Aufgaben an einen Threadpool senden, sollte der letzte Benutzer, der die Ausführung abschließen soll, dem GUI-Thread signalisieren, dass der Job abgeschlossen ist. In der Regel muss dazu ein Objekt aufgerufen werden, das die verbleibenden Aufgaben / Threads und Signale zählt, wenn der letzte ausgelöst wird. Sehen Sie sich System.Threading.CountdownEvent an.
Es gibt eine alternative Methode, die die CountdownEvent-Klasse verwendet.
Der Code, der die Threads startet, muss einen Zähler erhöhen und ein CountdownEvent-Objekt an jeden Thread übergeben. Jeder Thread wird CountdownEvent.Signal () aufrufen, wenn es fertig ist.
Der folgende Code veranschaulicht diesen Ansatz:
%Vor%Brians Lösung ist nicht vollständig und erzeugt einen Syntaxfehler. Ohne den Syntaxfehler würde es funktionieren und das Problem des ursprünglichen Posters lösen. Ich weiß nicht, wie ich den Syntaxfehler beheben soll, daher posten wir diese Frage, damit die erste Frage gelöst werden kann. Bitte löschen Sie diese Nachricht nicht. es ist relevant für die anfängliche Frage, die beantwortet wird.
@Brian Gideon: Ihre Lösung wäre perfekt mit Ausnahme des folgenden Codes:
%Vor%Das spezielle Problem dabei ist in der () = & gt; Portion. Das erzeugt einen Syntaxfehler, der liest Delegate System.Action "System.Threading.Tasks.Task" benötigt 0 Argumente nicht
Ich wünschte wirklich, das würde funktionieren und ich kenne die Lösung dafür nicht. Ich habe versucht, den Fehler nachzuschlagen, aber ich verstehe nicht, welche Parameter er benötigt. Wenn jemand dies beantworten kann, wäre das sehr hilfreich. Dies ist das einzige fehlende Teil dieses Problems.
Lassen Sie uns zuerst etwas aus dem Weg räumen.
Thread.Join
, WaitHandle.WaitOne
oder einen anderen Blockierungsmechanismus aufrufen. So würde ich das mit der TPL machen.
%Vor% Was ich hier mache, ist die Erstellung einer übergeordneten Aufgabe, die selbst untergeordnete Aufgaben ausführt. Beachten Sie, dass ich TaskCreationOptions.AttachedToParent
verwende, um die untergeordneten Aufgaben mit ihren Eltern zu verknüpfen. Dann rufe ich in der Elternaufgabe ContinueWith
auf, was ausgeführt wird, nachdem der Elternteil und alle seine Kinder abgeschlossen sind. Ich verwende TaskScheduler.FromCurrentSynchronizationContext
, um die Fortsetzung auf dem UI-Thread zu erhalten.
Und hier ist eine alternative Lösung mit Parallel.ForEach
. Beachten Sie, dass es eine etwas sauberere Lösung ist.
Sie könnten WaitHandle
für jeden Thread erstellen, auf den Sie warten:
Fügen Sie ManualResetEvent
hinzu, um es aufzulisten und an thread weiterzuleiten:
Innerhalb der Thread-Methode:
%Vor%Der Haupt-Thread wird die Ausführung fortsetzen, wenn alle Threads ihre Warte-Handles setzen.
Tags und Links c# multithreading thread-safety