如果我增加就業機會與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