等到所有线程在ThreadPool中完成工作

我有这个代码:

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

我想知道所有线程池线程什么时候完成他们的工作。 我怎么能这样做?

您需要自己跟踪。

一个选项是使用计数器和重置事件:

 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"); 

在.NET Framework 4+中使用方便的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"); 

我不确定ThreadPool是否公开了这样的function,但你可以使用等待句柄,顺便说两次迭代似乎是不必要的:

 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); 

线程池不会告诉您线程何时完成执行,因此工作项必须自己执行。 我改变了这样的代码:

  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); 

我就是这样做的。

 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(); } } }