Ermitteln, wann alle Threads beendet sind c #

8

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%     
Derek 24.04.2012, 08:39
quelle

8 Antworten

10

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:

  • Sie sollten nicht eine große Anzahl von Threads erstellen - das explizite Erstellen von Hunderten von Threads ist keine gute Idee
  • Sie sollten andere Ansätze bevorzugen - versuchen Sie Parallel.ForEach und System.Threading.Task . In diesen Tagen bietet .Net Ihnen eine Menge Hilfe bei der Arbeit mit Threading- und asynchronen Aufgaben - ich würde Ihnen wirklich empfehlen, sich darüber zu informieren, anstatt zu versuchen, mit expliziten Threads zu arbeiten.
  • Dies sieht wie ein Klick-Handler aus. Sind es ASP.NET-Webformulare oder eine Desktopanwendung? Wenn der erste, würde ich sicherlich nicht empfehlen, viele Threads zum Ausführen von Hintergrundaufgaben aus der Anfrage hervorbringen. Möchten Sie in jedem Fall, dass Ihre Webseite oder GUI blockiert wird, während Sie auf die Fertigstellung der Threads warten?
Rob Levine 24.04.2012, 08:42
quelle
4

können Sie verwenden: IsAlive. Aber Sie haben eine Referenz wie

%Vor%     
jorne 24.04.2012 08:48
quelle
2

Eine weitere Idee wäre, Parallel.ForEach in einem separaten Thread zu verwenden: Dies ist auch sicher, wenn Sie zu viele Maschinen haben, die Sie reparieren können.

%Vor%     
weismat 24.04.2012 09:04
quelle
2

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.

    
Martin James 24.04.2012 09:35
quelle
2

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%     
Matthew Watson 24.04.2012 10:16
quelle
2

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.

    
Excuseme baking powder 02.08.2012 23:08
quelle
2

Lassen Sie uns zuerst etwas aus dem Weg räumen.

  • Erstelle keine einzelnen Threads dafür. Threads sind eine teure Ressource. Verwenden Sie stattdessen Thread-Pooling-Techniken.
  • Blockieren Sie den UI-Thread nicht, indem Sie 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.

%Vor%     
Brian Gideon 24.04.2012 13:28
quelle
1

Sie könnten WaitHandle für jeden Thread erstellen, auf den Sie warten:

%Vor%

Fügen Sie ManualResetEvent hinzu, um es aufzulisten und an thread weiterzuleiten:

%Vor%

Innerhalb der Thread-Methode:

%Vor%

Der Haupt-Thread wird die Ausführung fortsetzen, wenn alle Threads ihre Warte-Handles setzen.

    
Sergey Berezovskiy 24.04.2012 08:55
quelle