我有一个C#Windows服务,可以启动各种对象(类库)。这些对象中的每一个都有自己的“处理”逻辑,通过使用ThreadPool
启动多个长时间运行的处理线程。我有一个例子,就像这样:
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(WorkerThread_Processing));
这很有效。我的应用程序没有任何问题,我的线程运行良好。
现在,对于回归测试,我启动了相同的对象,但是从C#Console应用程序而不是Windows服务。它调用相同的确切代码(因为它调用相同的对象),但WorkerThread_Processing
方法在启动前延迟最多20秒。
我已经进入并从ThreadPool
切换到Thread
,问题就消失了。这可能发生什么?我知道我没有超过MaxThreads
计数(我最多开始20个线程)。
答案 0 :(得分:15)
ThreadPool
特别是不用于长期运行的项目(更具体地说,当您使用ThreadPool
时,您甚至不一定要启动新线程,它的目的是将任务分布在有限数量的线程上。)
如果您的任务长时间运行,您应该将其分解为放在ThreadPool
上的逻辑部分(或使用新的Task
框架),或者启动您自己的{{1对象。
至于为什么您遇到了延迟,MSDN Documentation for the ThreadPool
class说明了以下内容:
作为其线程管理策略的一部分,线程池在创建线程之前会延迟。因此,当许多任务在短时间内排队时,在所有任务开始之前可能会有很长的延迟。
您只知道Thread
尚未达到其最大线程数,而不是它实际处于空闲状态的线程数(如果有)。
答案 1 :(得分:2)
线程池的最大线程数值是它可以创建的最大数量。它不是已创建的最大数量。线程池有逻辑阻止它立即旋转一大堆线程。
如果快速连续调用ThreadPool.QueueUserWorkItem
10次,则线程池不会立即创建10个线程。它会启动一个线程,延迟,启动另一个等等。
我似乎记得延迟是500毫秒,但我找不到要验证的文档。
线程池有内置延迟(在.NET中半秒) 框架版本2.0)在启动新的空闲线程之前。如果你的 应用程序会在短时间内定期启动许多任务 空闲线程数量的增加可以产生显着的 吞吐量增加。设置空闲线程数太高 不必要地消耗系统资源。
您可以控制线程维护的空闲线程数 使用GetMinThreads和SetMinThreads
进行池化
请注意,此引用来自.NET 3.5版本的文档。 .NET 4.0版本没有提到延迟。