2010-03-08 16 views
5

Ich verwende mehrere Threads in meiner Anwendung mit while (true) Schleife und jetzt möchte ich aus Schleife beenden, wenn alle aktiven Threads ihre Arbeit abschließen.Wie ermitteln Sie, ob untergeordnete Threads abgeschlossen wurden

+0

Nicht ganz unähnlich dieser Frage & Antwort: http://stackoverflow.com/questions/435668/code-for-a-simple-thread-pool -in-c – xcud

+0

Was ist deine Schleife? Verwenden Sie es zum Erstellen von Threads? Oder verwenden Sie es, um auf Threads zu warten, um dort Aufgaben abzuschließen? – ata

Antwort

1

Sie können Process.GetCurrentProcess(). Threads.Count verwenden.

+0

Die Lösung Process.GetCurrentProcess() .Threads.Count funktioniert nicht. Es gibt alle laufenden Prozesse zurück, aber ich brauche die Anzahl der laufenden Threads, die ich in meiner Anwendung erstellt habe. –

+0

Process.GetCurrentProcess(). Threads.Count gibt tatsächlich die Anzahl der Threads für den aktuellen Prozess zurück, wenn Sie alle Threads aller Prozesse zählen müssen, die Sie benötigen, um Denkprozesse in Ihrer Anwendung zu wiederholen – Anonymous

+0

Dazu gehören auch Thread-Pool-Threads. Obwohl Sie die Anzahl erhalten können, bevor Sie einen Thread erstellen, wird dies jedoch nicht garantieren, dass Ihre benutzerdefinierten Threads beendet werden, wenn der Zählerstand sinkt. – ata

1

Es gibt verschiedene Ansätze hier, aber utlimately die meisten von ihnen kommen zu Ihrem Wechsel des ausgeführten Threads etwas zu tun, wann immer sie (Erfolg oder über Ausnahme, die Sie nicht wollen, zu tun sowieso) verlassen. Ein einfacher Ansatz könnte darin bestehen, Interlock.Decrement zu verwenden, um einen Zähler zu reduzieren - und wenn er Null ist (oder -ve, was wahrscheinlich einen Fehler bedeutet), ein ManualResetEvent oder Monitor.Pulse ein Objekt freizugeben; In beiden Fällen würde der Original Thread auf dieses Objekt warten. Eine Anzahl solcher Ansätze sind discussed here.

Natürlich könnte es einfacher sein, die TPL-Bits in 4.0 zu betrachten, die hier eine Menge neuer Optionen bieten (nicht zuletzt Dinge wie Parallel.For in PLINQ).

Wenn Sie eine synchronisierte Arbeitswarteschlange verwenden, ist es möglicherweise auch möglich, diese Warteschlange so einzurichten, dass sie sich selbst schließt und abwartet, bis die Warteschlange leer ist. Die Annahme, hier zu sein, dass Ihre Arbeitsthreads wie etwas tun:

T workItem; 
while(queue.TryDequeue(out workItem)) { // this may block until either something 
    ProcessWorkItem(workItem);   // todo, or the queue is terminated 
} 
// queue has closed - exit the thread 

in diesem Fall, sobald die Warteschlange all leer ist Ihre Worker-Threads bereits im Prozess des Selbstmordes sein sollten.

5

Angenommen, Sie haben eine Liste der Threads selbst, hier sind zwei Ansätze.

Lösung, um die erste:

Verwenden Thread.Join() mit einem Zeitspanne Parametern mit jedem Thread wiederum synch auf. Der Rückgabewert sagt Ihnen, ob der Thread beendet ist oder nicht.

Lösung der zweite:

prüfen Thread.IsAlive() zu sehen, ob der Faden noch läuft. Stellen Sie in beiden Fällen sicher, dass Ihr Hauptthread Prozessorzeit für die ausgeführten Threads liefert, andernfalls wird Ihre Warteschleife am meisten/die gesamte CPU verbrauchen und Ihre Worker-Threads verhungern.

+0

Im Falle von Join, wird der Thread, der die Join-Methode aufruft, auf die Rückkehr warten. Im Falle von Thread.IsAlive müssen Sie eine bestimmte Anzahl von Zeit (wie 1 Sekunde) abfragen. Es wäre dasselbe wie der Aufruf der Join-Methode, der aufrufende Thread muss warten, bis alle Threads beendet sind. Verwenden Sie besser Thread.Join() – ata

+0

Der Hauptunterschied besteht darin, dass das Abrufen von IsAlive() Ihrem Hauptthread ermöglicht, andere Arbeit fortzusetzen, falls vorhanden. Gute Punkte jedoch - wenn es keine Arbeit zu erledigen gibt, ist Join() die effizientere Wahl. – Bevan

0

Sie können Thread.Join() verwenden. Die Join-Methode blockiert den aufrufenden Thread, bis der Thread (derjenige, auf dem die Join-Methode aufgerufen wird) beendet wird.

Wenn Sie also eine Thread-Liste haben, können Sie durchschleifen und Join für jeden Thread aufrufen. Die Schleife wird nur beendet, wenn alle Threads leer sind. So etwas wie das:

for(int i = 0 ;i < childThreadList.Count; i++) 
{ 
    childThreadList[i].Join(); 
} 
///...The following code will execute when all threads in the list have been terminated.../// 
0

Ich finde, dass die Verwendung der Join() -Methode der sauberste Weg ist. Ich benutze häufig mehrere Threads, und jeder Thread lädt typischerweise Daten aus verschiedenen Datenquellen (Informix, Oracle und SQL zur gleichen Zeit). Eine einfache Schleife, wie oben erwähnt, ruft Join() für jedes Thread-Objekt auf ein einfaches List-Objekt) funktioniert !!!

Carlos Merighe.

0

Ich ziehe eine HashSet von Themen mit:

// create a HashSet of heavy tasks (threads) to run 
HashSet<Thread> Threadlist = new HashSet<Thread>(); 
Threadlist.Add(new Thread(() => SomeHeavyTask1())); 
Threadlist.Add(new Thread(() => SomeHeavyTask2())); 
Threadlist.Add(new Thread(() => SomeHeavyTask3())); 

// start the threads 
foreach (Thread T in Threadlist) 
    T.Start(); 

// these will execute sequential 
NotSoHeavyTask1(); 
NotSoHeavyTask2(); 
NotSoHeavyTask3(); 

// loop through tasks to see if they are still active, and join them to main thread 
foreach (Thread T in Threadlist) 
    if (T.ThreadState == ThreadState.Running) 
    T.Join(); 

// finally this code will execute 
MoreTasksToDo(); 
Verwandte Themen