【问题标题】:Why is ThreadPool.SetMinThreads not changing the minimum value?为什么 ThreadPool.SetMinThreads 不改变最小值?
【发布时间】:2013-01-27 03:06:05
【问题描述】:

使用 .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

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

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

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

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

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

【问题讨论】:

  • This is about 3.5 但可能相关...
  • 我确实发现了关于 .NET 3.5 的错误,但问题涉及异步 I/O 线程,而不是工作线程。不过,谢谢。
  • ASP.NET 很重要。又叫什么“回收应用程序池”?这当然也会重置线程池。

标签: c# performance threadpool


【解决方案1】:

我会建议另一种方法。

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

如果您有 IO 密集型操作,请在每个阶段进行异步操作。

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

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

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

【讨论】:

  • 如果我有能力,我会照你说的做。不幸的是,.NET 对整个应用程序使用单个线程池,并且所有计时器线程都在这个线程池之外运行。我不相信此应用程序中的任何代码明确使用线程池。所有(或几乎所有)使用都是隐式的,例如通过计时器。
  • @Eddie:当然。那么我想知道两件事......(a)您在计时器回调中消耗了什么样的工作负载(b)您正在使用哪种计时器(它在哪个命名空间中)?
  • 定时器回调做不同的事情。这里的关键是进行预期是及时的 SOAP 调用(+/- 十几秒左右)。计时器是System.Timers.Timer() 的一个实例。由于基本上所有系统线程池的使用都是隐式的,老实说,我不确定它的全部用途。 ASP.NET 自托管利用了那个线程池,对吧?如果有办法让某些计时器使用私有线程池,那就更好了。
猜你喜欢
  • 1970-01-01
  • 2020-09-06
  • 2020-02-24
  • 2019-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-09
相关资源
最近更新 更多