Espera hasta que todos los hilos terminen su trabajo en ThreadPool

tengo este codigo

var list = new List(); for(int i=0;i<10;i++) list.Add(i); for(int i=0;i { Console.WriteLine(x); }), list[i]); } 

Y quiero saber cuándo todos los subprocesos de subprocesos terminaron su trabajo. ¿Cómo puedo hacer eso?

Tendrás que seguir esto tú mismo.

Una opción para esto es usar un contador y un evento de reinicio:

 int toProcess = 10; using(ManualResetEvent resetEvent = new ManualResetEvent(false)) { var list = new List(); for(int i=0;i<10;i++) list.Add(i); for(int i=0;i<10;i++) { ThreadPool.QueueUserWorkItem( new WaitCallback(x => { Console.WriteLine(x); // Safely decrement the counter if (Interlocked.Decrement(ref toProcess)==0) resetEvent.Set(); }),list[i]); } resetEvent.WaitOne(); } // When the code reaches here, the 10 threads will be done Console.WriteLine("Done"); 

En .NET Framework 4+ use la práctica clase System.Threading.CountdownEvent:

 const int threadCount = 10; var list = new List(threadCount); for (var i = 0; i < threadCount; i++) list.Add(i); using (var countdownEvent = new CountdownEvent(threadCount)) { for (var i = 0; i < threadCount; i++) ThreadPool.QueueUserWorkItem( x => { Console.WriteLine(x); countdownEvent.Signal(); }, list[i]); countdownEvent.Wait(); } Console.WriteLine("done"); 

No estoy seguro de si ThreadPool expone dicha funcionalidad, pero puede usar los manejadores de espera y, por cierto, parece innecesario iterar dos veces:

 var events = new ManualResetEvent[10]; var list = new List(); for (int i = 0; i < 10; i++) { list.Add(i); events[i] = new ManualResetEvent(false); int j = i; ThreadPool.QueueUserWorkItem(x => { Console.WriteLine(x); events[j].Set(); }, list[i]); } WaitHandle.WaitAll(events); 

El grupo de subprocesos no le dice cuándo el subproceso ha terminado de ejecutarse, por lo que el elemento de trabajo debe hacerlo por sí mismo. Cambié el código así:

  var list = new List(); ManualResetEvent[] handles = new ManualResetEvent[10]; for (int i = 0; i < 10; i++) { list.Add(i); handles[i] = new ManualResetEvent(false); } for (int i = 0; i < 10; i++) { ThreadPool.QueueUserWorkItem( new WaitCallback(x => { Console.WriteLine(x); handles[(int) x].Set(); }), list[i]); } WaitHandle.WaitAll(handles); 

Así es como lo haría.

 class Program { static void Main(string[] args) { var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; using (var countdown = new Countdown(items.Length)) { foreach (var item in items) { ThreadPool.QueueUserWorkItem(o => { Thread.SpinWait(100000000); Console.WriteLine("Thread Done!"); countdown.Signal(); }); } countdown.Wait(); } Console.WriteLine("Job Done!"); Console.ReadKey(); } public class Countdown : IDisposable { private readonly ManualResetEvent done; private readonly int total; private volatile int current; public Countdown(int total) { this.total = total; current = total; done = new ManualResetEvent(false); } public void Signal() { lock (done) { if (current > 0 && --current == 0) done.Set(); } } public void Wait() { done.WaitOne(); } public void Dispose() { done.Dispose(); } } }