为什么ThreadPool.SetMinThreads没有更改最小值

本文关键字:最小值 ThreadPool SetMinThreads 为什么 | 更新日期: 2023-09-27 17:58:54

在.NET 4.0运行时编译和运行,我有这样的代码:

int MinWorkerThreads, MaxWorkerThreads;
int MinCompletionPortThreads, MaxCompletionPortThreads;
ThreadPool.GetMinThreads(out MinWorkerThreads, out MinCompletionPortThreads);
ThreadPool.GetMaxThreads(out MaxWorkerThreads, out MaxCompletionPortThreads);
_logger.Info("Default thread pool settings min/max:");
_logger.Info("Worker thread: " + MinWorkerThreads + " / " + MaxWorkerThreads);
_logger.Info("IO thread    : " + MinCompletionPortThreads + " / " + MaxCompletionPortThreads);
_logger.Info("Setting minimum default worker thread count to " + Config.MinWorkerThreads);
if (!ThreadPool.SetMinThreads(Config.MinWorkerThreads, MinCompletionPortThreads))
{
    _logger.Warn("Unable to modify the minimum number of worker threads");
}
ThreadPool.GetMinThreads(out MinWorkerThreads, out MinCompletionPortThreads);
_logger.Info("Worker thread: " + MinWorkerThreads + " / " + MaxWorkerThreads);

我的日志输出如下:

Default thread pool settings min/max:
Worker thread: 4 / 32767
IO thread    : 4 / 1000
Setting minimum default worker thread count to 50
Worker thread: 50 / 32767

该值会立即更改,但不会永久更改。

我为什么要这么做?Timer使用默认的线程池,我见过一些时候,突然一批任务进入系统线程池,淹没了它,导致一些本应每15秒触发一次的计时器延迟了60秒以上。

问题是,当我在运行时15分钟内使用相同的代码转储相同的信息时,我会得到非常不同的值:

Worker thread: 4 / 400
IO thread    : 4 / 400

有没有更好的方法可以在不放弃使用System.Timers.Timer的情况下解决这个问题?在完全不涉及IIS的独立C#应用程序中,如何重置此值?如果您是自托管ASP.NET,这会隐式地更改系统线程池的调优吗?

为什么ThreadPool.SetMinThreads没有更改最小值

我建议采用另一种方法。

从ThreadPool中消除所有阻塞代码。这不是它的设计目的。

如果您有IO绑定操作,请在每个阶段都采用异步操作。

如果您有CPU绑定操作,请不要在ThreadPool线程中运行它们。

通过严格遵守这些规则,您永远不应该篡改ThreadPool参数。正如您所注意到的,有太多的.Net API完全依赖于响应线程池。如果你只是在吞噬线程,那么无论你选择多少,如果你运行程序足够长/足够努力,你很可能会再次达到极限。

按预期使用ThreadPool。。。短命逻辑,主要用于将IO结果编组到正确的位置。