ThreadPool.QueueUserWorkItem 中的最大排队元素数

发布于 2024-08-18 09:15:10 字数 110 浏览 7 评论 0原文

我将最大线程设置为 10。然后我使用 ThreadPool.QueueUserWorkItem 添加了 22000 个任务。 运行程序后很可能没有完成所有22000个任务。可用线程排队的任务数量是否有限制?

I set the max thread to 10. Then I added 22000 task using ThreadPool.QueueUserWorkItem.
It is very likely that not all the 22000 task was completed after running the program. Is there a limitation how many task can be queued for avaiable threads?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

淡淡離愁欲言轉身 2024-08-25 09:15:10

如果您需要等待所有任务处理完毕,则需要自己处理。 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 个左右的单个工作项目可能会对您的整体吞吐量有很大帮助......

If you need to wait for all of the tasks to process, you need to handle that yourself. The ThreadPool threads are all background threads, and will not keep the application alive.

This is a relatively clean way to handle this type of situation:

 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();
 }

That being said, it's usually better to "group" together your work items if you have thousands of them, and not treat them as separate Work Items for the threadpool. This is some overhead involved in managing the list of items, and since you won't be able to process 22000 at a time, you're better off grouping these into blocks. Having single work items each process 50 or so will probably help your overall throughput quite a bit...

请你别敷衍 2024-08-25 09:15:10

队列没有实际限制,但池本身不会超过 64 个等待句柄,即活动线程总数。

The queue has no practical limit however the pool itself will not exceed 64 wait handles, ie total threads active.

梦途 2024-08-25 09:15:10

这是一个依赖于实现的问题,并且该函数的实现随着时间的推移发生了一些变化。但在 .Net 4.0 中,您基本上受到系统内存量的限制,因为任务存储在内存队列中。您可以通过深入研究 Reflector 中的实现来看到这一点。

This is an implementation dependent question and the implementation of this function has changed a bit over time. But in .Net 4.0, you're essentially limited by the amount of memory in the system as the tasks are stored in an in memory queue. You can see this by digging through the implementation in reflector.

甜心小果奶 2024-08-25 09:15:10

来自 ThreadPool 文档

注意:托管线程池中的线程是后台线程。也就是说,它们的 IsBackground 属性为 true。这意味着在所有前台线程退出后,ThreadPool 线程将不会让应用程序保持运行。

您是否有可能在处理完所有任务之前退出?

From the documentation of ThreadPool:

Note: The threads in the managed thread pool are background threads. That is, their IsBackground properties are true. This means that a ThreadPool thread will not keep an application running after all foreground threads have exited.

Is it possible that you're exiting before all tasks have been processed?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文