我已经设置了这样的线程池:
ThreadPool.SetMaxThreads(10000, 10000);
ThreadPool.SetMinThreads(20, 20);
但是,我的应用程序开始在重载下挂起。这似乎是因为工作人员的任务没有执行:我曾使用ThreadPool.QueueUserWorkItem
来运行一些任务,这些任务又使用相同的方法来排队进一步的工作。这对于有限的线程池(死锁情况)显然是危险的,但我使用的线程池不是为了限制最大线程,而是为了减少线程创建开销。
我可以在那里看到潜在的陷阱,但我相信在池上设置最多10000个线程意味着如果一个项目排队,所有线程都很忙,并且池中没有10000个线程,将创建一个新任务并在那里处理任务。
然而,我改为:
ThreadPool.SetMaxThreads(10000, 10000);
ThreadPool.SetMinThreads(200, 200);
..而且应用程序开始工作了。如果这让它开始工作,我是否遗漏了线程池如何/何时从最小尺寸扩展到最大尺寸?
答案 0 :(得分:4)
线程池调度程序的工作是确保没有比cpu核心更多的执行TP线程。默认最小值等于核心数。一个幸福的数字,因为它最小化了线程上下文切换引起的开销。如果现有的线程没有完成,调度程序会逐步进入并允许另一个线程执行。
因此,如果线程无法完成,则需要一小时二十分钟才能达到新的最大值。它很可能永远不会到达那里,当2000个线程占用了所有可用的虚拟内存时,32位机器将会关注它。您可以在具有非常大的页面文件的64位操作系统上进行操作。为避免分页死亡需要大量的RAM,你需要至少12千兆字节。
通用诊断是您不恰当地使用TP线程。它们耗时太长,通常是由I / O阻塞引起的。常规线程是这类工作的正确选择。这可能现在很难解决,特别是因为你对你得到的东西感到满意。提高最低限度确实是一个快速的解决方法。由于TP调度程序不能再做一个合理的工作,你必须手动调整它。
答案 1 :(得分:3)
答案 2 :(得分:2)
您描述的性能问题与此ASP.NET知识库文章
中记录的内容类似http://support.microsoft.com/kb/821268
总而言之,您需要仔细选择参数(本文提到了默认ASP.NET线程池的典型设置,但您可以将该技巧应用到您的应用程序),并根据性能测试和特征进一步调整它们你的应用程序。
请注意,您对负载的了解越多,您就会发现“重载”不再是描述情况的好词。有时您需要进一步对案例进行分类,以包括详细的术语,例如爆发负载等。
答案 3 :(得分:1)
如果您的逻辑依赖于拥有最少量的线程,则需要立即更改。
设置MinThreads为200(甚至20)会浪费相当多的内存。请注意,MaxThreads在这里不相关,你可能没有10 GB内存。
200分钟帮助你的事实是可疑的,作为解决方案,它可能非常脆弱。
查看正常的生产者/消费者模式,和/或使用有界队列来结合您的任务。