ThreadPool行为:不从最小大小增长

时间:2012-02-12 10:48:43

标签: c# multithreading threadpool

我已经设置了这样的线程池:

ThreadPool.SetMaxThreads(10000, 10000);
ThreadPool.SetMinThreads(20, 20);

但是,我的应用程序开始在重载下挂起。这似乎是因为工作人员的任务没有执行:我曾使用ThreadPool.QueueUserWorkItem来运行一些任务,这些任务又使用相同的方法来排队进一步的工作。这对于有限的线程池(死锁情况)显然是危险的,但我使用的线程池不是为了限制最大线程,而是为了减少线程创建开销。

我可以在那里看到潜在的陷阱,但我相信在池上设置最多10000个线程意味着如果一个项目排队,所有线程都很忙,并且池中没有10000个线程,将创建一个新任务并在那里处理任务。

然而,我改为:

ThreadPool.SetMaxThreads(10000, 10000);
ThreadPool.SetMinThreads(200, 200);

..而且应用程序开始工作了。如果这让它开始工作,我是否遗漏了线程池如何/何时从最小尺寸扩展到最大尺寸?

4 个答案:

答案 0 :(得分:4)

线程池调度程序的工作是确保没有比cpu核心更多的执行TP线程。默认最小值等于核心数。一个幸福的数字,因为它最小化了线程上下文切换引起的开销。如果现有的线程没有完成,调度程序会逐步进入并允许另一个线程执行。

因此,如果线程无法完成,则需要一小时二十分钟才能达到新的最大值。它很可能永远不会到达那里,当2000个线程占用了所有可用的虚拟内存时,32位机器将会关注它。您可以在具有非常大的页面文件的64位操作系统上进行操作。为避免分页死亡需要大量的RAM,你需要至少12千兆字节。

通用诊断是您不恰当地使用TP线程。它们耗时太长,通常是由I / O阻塞引起的。常规线程是这类工作的正确选择。这可能现在很难解决,特别是因为你对你得到的东西感到满意。提高最低限度确实是一个快速的解决方法。由于TP调度程序不能再做一个合理的工作,你必须手动调整它。

答案 1 :(得分:3)

无论何时使用线程池,您都可以使用它的“线程注入和退出算法”。

该算法没有正确记录(我知道)并且不可配置。

如果您正在使用“任务”,则可以编写自己的Task Scheduler

答案 2 :(得分:2)

您描述的性能问题与此ASP.NET知识库文章

中记录的内容类似

http://support.microsoft.com/kb/821268

总而言之,您需要仔细选择参数(本文提到了默认ASP.NET线程池的典型设置,但您可以将该技巧应用到您的应用程序),并根据性能测试和特征进一步调整它们你的应用程序。

请注意,您对负载的了解越多,您就会发现“重载”不再是描述情况的好词。有时您需要进一步对案例进行分类,以包括详细的术语,例如爆发负载等。

答案 3 :(得分:1)

如果您的逻辑依赖于拥有最少量的线程,则需要立即更改。

设置MinThreads为200(甚至20)会浪费相当多的内存。请注意,MaxThreads在这里不相关,你可能没有10 GB内存。

200分钟帮助你的事实是可疑的,作为解决方案,它可能非常脆弱。

查看正常的生产者/消费者模式,和/或使用有界队列来结合您的任务。