我将最大线程设置为10.然后我使用ThreadPool.QueueUserWorkItem添加了22000任务。 运行该程序后很可能并非所有22000任务都已完成。是否可以为可用线程排队多少任务?
答案 0 :(得分:12)
如果您需要等待处理所有任务,您需要自己处理。 ThreadPool线程都是后台线程,不会使应用程序保持活动状态。
这是处理此类情况的一种相对干净的方法:
using (var mre = new ManualResetEvent(false))
{
int remainingToProcess = workItems.Count(); // Assuming workItems is a collection of "tasks"
foreach(var item in workItems)
{
// Delegate closure (in C# 4 and earlier) below will
// capture a reference to 'item', resulting in
// the incorrect item sent to ProcessTask each iteration. Use a local copy
// of the 'item' variable instead.
// C# 5/VS2012 will not require the local here.
var localItem = item;
ThreadPool.QueueUserWorkItem(delegate
{
// Replace this with your "work"
ProcessTask(localItem);
// This will (safely) decrement the remaining count, and allow the main thread to continue when we're done
if (Interlocked.Decrement(ref remainingToProcess) == 0)
mre.Set();
});
}
mre.WaitOne();
}
话虽这么说,如果你有数千个工作项,通常最好将它们“组合”在一起,而不是将它们视为线程池的单独工作项。这是管理项目列表所涉及的一些开销,并且由于您一次无法处理22000,因此最好将这些组合成块。每个过程50个左右的单个工作项可能会帮助您提高整体吞吐量......
答案 1 :(得分:6)
队列没有实际限制,但池本身不会超过64个等待句柄,即总线程处于活动状态。
答案 2 :(得分:4)
来自documentation of ThreadPool:
注意:托管线程池中的线程是后台线程。也就是说,它们的IsBackground属性是真的。这意味着在所有前台线程退出后,ThreadPool线程不会使应用程序继续运行。
您是否有可能在处理完所有任务之前退出?
答案 3 :(得分:4)
这是一个依赖于实现的问题,随着时间的推移,这个功能的实现已经发生了一些变化。但是在.Net 4.0中,由于任务存储在内存队列中,因此您基本上受限于系统中的内存量。您可以通过挖掘反射器中的实现来看到这一点。