ThreadPool.SetMinThreads 不创建任何新线程

ThreadPool.SetMinThreads does not create any new threads

我想弄清楚 ThreadPool.SetMinThreads 到底有什么影响。

根据official documentation它说

Sets the minimum number of threads the thread pool creates on demand, as new requests are made, before switching to an algorithm for managing thread creation and destruction.

据我所知,作为一名开发人员,我应该可以控制如何按需旋转新线程的机制,因此它们会在空闲状态下创建并等待,例如在我期待在特定时间收到请求负载。

这正是我最初认为 SetMinThreads 方法的设计目的。

但是当我真正开始使用它时 - 我得到了非常奇怪的结果。

所以我有我的 ASP.NET .NET5 应用程序,在控制器操作中我有这样的代码: ThreadPool.SetMinThreads(32000, 1000);

当然,我直觉地期望运行时为我创建 32K 的工作线程和 1000 个 io 线程。

当我这样做,然后调用其他方法 - Process.GetCurrentProcess().Threads 获取所有进程的线程,并在它们上打印统计信息时,我得到类似这样的结果

Standby - 17
Running - 4

我认为应用可能需要一些时间来启动新线程,所以我尝试了不同的延迟,1 分钟、5 分钟和 10 分钟。

但结果始终保持不变,我得到 15-20 Standby2-4 Running.

然后是合乎逻辑的问题 - SetMinThreads 方法到底在做什么? MSDN提供的描述好像不是很有帮助。

另一个合乎逻辑的问题 - 如果我想强制 dotnet 在空闲状态下旋转 32K 的新线程怎么办 - dotnet 是否为此提供任何机制?

ThreadPool.SetMinThreads 设置ThreadPool 立即按需 创建的最小线程数。这是关键短语,它确实很不直观。 ThreadPool 当前¹ (.NET 5) 在两种模式下工作:

  1. 当一个新的工作请求到达,并且池中的所有线程都忙时,立即创建一个新线程以满足请求。

  2. 当一个新的工作请求到达,并且池中的所有线程都忙时,将请求排队,并在创建新线程之前等待 1 秒,希望同时有一个工作线程将完成其当前工作,并可用于处理排队的请求。

ThreadPool.SetMinThreads 设置了这两种模式之间的阈值。它 而不是 让您可以控制当前处于活动状态的线程数。这不是很令人满意,但事实就是如此。如果要强制 ThreadPool 立即创建 1,000 个线程,除了调用 ThreadPool.SetMinThreads(1000, 1000) 之外,还必须发送相同数量的工作请求。这样的事情应该可以解决问题:

ThreadPool.SetMinThreads(1000, 1000);
Task[] tasks = Enumerable.Range(0, 1000)
    .Select(_ => Task.Run(() => Thread.Sleep(100)))
    .ToArray();

老实说,我认为没有人这样做。创建一个新的 Thread 在人类时间上相当快(在我的 PC 中每个线程大约需要 0.25 毫秒),因此对于接收人类请求的系统,创建线程的开销应该不会产生任何可衡量的影响。另一方面,0.25 毫秒在计算机时间中是一个 eon,当您希望线程执行少量工作(在纳秒范围内)时,例如在 List<T> 中添加一些内容。这就是 ThreadPool 首先被发明的原因:为了分摊为微小但大量的工作负载创建线程的开销。

请注意,创建一个新的 Thread 也有内存成本,这通常比时间成本更显着:每个线程至少需要 of RAM for its stack. So creating 32,000 threads will tie down 32 GB of memory just for stack space. This is not very efficient. That's why in recent years asynchronous programming 在服务器端变得如此突出web 开发,因为它允许用更少的线程做更多的工作。

¹ 没有什么能阻止 Microsoft 工程师将来 changing/twicking 实施 ThreadPool。据我所知,这在过去至少发生过一次。