C# 线程池未立即启动新线程

C# 线程池未立即启动新线程,c#,multithreading,console-application,C#,Multithreading,Console Application,我有一个C#Windows服务,可以启动各种对象(类库)。每个对象都有自己的“处理”逻辑,通过使用ThreadPool启动多个长时间运行的处理线程。我有一个例子,就像这样: System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(WorkerThread_Processing)); 这很有效。我的应用程序工作正常,线程工作正常 现在,对于回归测试,我正在启动这些相同的对象,但是是从C#Con

我有一个C#Windows服务,可以启动各种对象(类库)。每个对象都有自己的“处理”逻辑,通过使用
ThreadPool
启动多个长时间运行的处理线程。我有一个例子,就像这样:

System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(WorkerThread_Processing));
这很有效。我的应用程序工作正常,线程工作正常

现在,对于回归测试,我正在启动这些相同的对象,但是是从C#Console应用程序而不是Windows服务启动的。它调用相同的精确代码(因为它调用的是相同的对象),但是
WorkerThread\u Processing
方法在启动前会延迟20秒


我已经进入并从
线程池
切换到
线程
,问题就消失了。这里会发生什么?我知道我没有超过
MaxThreads
计数(我最多开始20个线程)。

ThreadPool
特别不适用于长时间运行的项目(更具体地说,当您使用
线程池时,您甚至不必启动新线程,因为它的目的是将任务分散到有限数量的线程上)

如果您的任务是长时间运行的,您应该将其分解为放在
线程池
上的逻辑部分(或者使用新的
任务
框架),或者旋转您自己的
线程
对象

至于您为什么会遇到延迟,报告如下所示:

作为其线程管理策略的一部分,线程池在创建线程之前会延迟。因此,当许多任务在短时间内排队时,在所有任务启动之前可能会有明显的延迟


您只知道
ThreadPool
尚未达到其最大线程数,而不知道有多少线程(如果有)它实际上处于空闲状态。

线程池的“最大线程数”值是它可以创建的最大线程数。它不是已经创建的最大线程数。线程池具有防止它立即旋转整个线程组的逻辑

如果连续快速调用
ThreadPool.QueueUserWorkItem
10次,线程池将不会立即创建10个线程。它将启动一个线程、延迟、启动另一个线程等

我似乎记得延迟是500毫秒,但我找不到文档来验证这一点

给你:

线程池具有内置延迟(在.NET中为半秒) 在启动新的空闲线程之前,如果 应用程序在很短的时间内周期性地启动许多任务,时间很短 空闲线程数量的增加会产生显著的影响 吞吐量增加。将空闲线程数设置得过高 不必要地消耗系统资源

您可以控制线程维护的空闲线程数 通过使用GetMinThreads和SetMinThreads


请注意,此引文摘自.NET 3.5版本的文档。

好的,谢谢您提供的信息!我将用Thread对象替换它们,并查看Task对象以供将来开发。谢谢!但是如果有延迟,为什么会导致延迟(假设有延迟)池中剩余的空闲线程?我同意这个结论,但没有找到令人满意的答案来回答原因。@pst:你不知道池中还有空闲线程,你知道
ThreadPool
尚未达到其最大线程数。根据,
ThreadPool
将延迟创建新的threads,所以一次添加几个项目几乎肯定会导致延迟。请参阅我的编辑。谢谢!@Adam Robinson更透彻的回答,+1。这绝对不应该发生,我也不会发生。你的控制台应用程序还做了什么吗?如果你创建一个全新的控制台应用程序并放入
ThreadPool.QueueUserWorkItem(o=>Console.WriteLine(“测试”))
它是否做了同样的事情?另外,如果您想查看线程池正在做什么,我建议您运行Process Explorer,并密切关注进程中的线程。您可以看到有多少线程池线程正在旋转。如果您的操作需要很长时间才能完成,则可能需要一段时间才能快速增加到20个线程。需要注意的一点是
ThreadPool.SetMinThreads
实际上并没有增加线程池中维护的空闲线程数。这只是意味着,当实际线程数低于该数字时,线程池将根据需要创建新线程,而不是等待前一个线程完成。