ThreadPool.QueueUserWorkItem中的最大排队元素

时间:2010-01-19 18:07:46

标签: c# .net multithreading threadpool

我将最大线程设置为10.然后我使用ThreadPool.QueueUserWorkItem添加了22000任务。 运行该程序后很可能并非所有22000任务都已完成。是否可以为可用线程排队多少任务?

4 个答案:

答案 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中,由于任务存储在内存队列中,因此您基本上受限于系统中的内存量。您可以通过挖掘反射器中的实现来看到这一点。