等待QueueUserWorkItem完成
如果我使用QueueUserWorkItem
向线程池添加作业…如何在完成所有作业之前使程序继续运行?
我知道我可以添加一些逻辑来保持应用程序不运行直到所有作业都完成,但我想知道是否有类似Thread.Join()
或者是否有任何方法来检索正在分配作业的每个线程。
您可以使用事件进行同步。 像这样:
private static ManualResetEvent resetEvent = new ManualResetEvent(false); public static void Main() { ThreadPool.QueueUserWorkItem(arg => DoWork()); resetEvent.WaitOne(); } public static void DoWork() { Thread.Sleep(5000); resetEvent.Set(); }
如果您不想将事件集嵌入到您的方法中,您可以执行以下操作:
var resetEvent = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem( arg => { DoWork(); resetEvent.Set(); }); resetEvent.WaitOne();
对于多个项目:
var events = new List(); foreach(var job in jobs) { var resetEvent = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem( arg => { DoWork(job); resetEvent.Set(); }); events.Add(resetEvent); } WaitHandle.WaitAll(events.ToArray());
执行此操作的最佳方法是使用CountdownEvent
类。 这是一个相当完善的模式,并且具有可扩展性。
using (var finished = new CountdownEvent(1)) { foreach (var workitem in workitems) { var capture = workitem; // Used to capture the loop variable in the lambda expression. finished.AddCount(); // Indicate that there is another work item. ThreadPool.QueueUserWorkItem( (state) => { try { ProcessWorkItem(capture); } finally { finished.Signal(); // Signal that the work item is complete. } }, null); } finished.Signal(); // Signal that queueing is complete. finished.Wait(); // Wait for all work items to complete. }
您可以使用.NET的Barrier类来实现此目的。
Barrier barrier = new Barrier(3); for(int i = 0; i < 2; i++) { ThreadPool.QueueUserWorkItem( (state) => { foo(); barrier.SignalAndWait(); }, null); } barrier.SignalAndWait();