如果我增加就业机会与QueueUserWorkItem
线程池......我怎么把我的计划从直到所有的作业都完成前进?等待QueueUserWorkItem来完成
我知道我可以添加一些逻辑来阻止应用程序运行,直到完成所有作业,但我想知道是否有像Thread.Join()
之类的东西,或者是否有任何方法可以检索正在分配作业的每个线程。
如果我增加就业机会与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<ManualResetEvent>();
foreach(var job in jobs)
{
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(
arg =>
{
DoWork(job);
resetEvent.Set();
});
events.Add(resetEvent);
}
WaitHandle.WaitAll(events.ToArray());
这很容易在一段时间排队一个工作努力......但如果我有多个作业,然后我需要一个扣来控制呢?我不是吗?如果不是......这是如何适应多个排队工作? – PedroC88
@ PedroC88 - 更新了答案。 –
这有64个项目的限制。正如其他答案显示,有更多适合的结构来处理多个任务,但是如果您针对的是较早的配置文件,则可以使用单个事件并使用递减的Interlocked.Decrement –
的最好的方法是使用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 4以上。 – newprint
@BrianGideon优秀的答案!但是,我怎么能用'CountdownEvent'过早地取消线程呢?就像我在Windows窗体应用程序中使用它并且用户关闭表单一样,但有线程正在运行。 –
@JohnOdom:这个答案有点过时了。一个更现代的解决方案是使用任务并行库这样的东西。无论如何,列入TPL的是合作取消班。这是应该用来优雅地终止线程的东西。 –
您正在使用哪种版本的.NET? –
.NET版本2.0 – PedroC88