如何确定TPL使用的线程数?

3

我曾帮助一位客户处理了一个应用程序的问题,该应用程序在一段时间后停止工作(最终又重新开始工作了)。

问题出在当一个任务(Task)失败时,在任务中使用Thread.Sleep五秒钟。由于每两秒钟可能排队多达800个任务,如果其中许多作业失败并调用了Thread.Sleep,你可以想象这个问题有多严重。没有这些作业被标记为TaskCreationOptions.LongRunning

我重写了任务,所以不需要Thread.Sleep(或Task.Delay)。

然而,我对TaskScheduler(默认值)在这种情况下的行为很感兴趣。它是如何和何时增加线程数量的?


如果你可以使用 await Task.Delay(),那就能解决你的问题。 - svick
@svick:我已经解决了这个问题。那不是问题所在。 - jgauffin
1个回答

2
根据MSDN
在后台,任务被排队到线程池中,该线程池已经使用算法(例如爬坡)来确定和调整最大化吞吐量的线程数量。 线程池将具有根据环境而定的最大线程数。当您创建更多Task时,池可以并发运行它们,直到达到其最大线程数,此时任何进一步的任务都将排队等待。
如果要找出最大的ThreadPool线程数,可以使用System.Threading.ThreadPool.GetMaxThreads(需要传递两个输出int参数,一个将填充最大工作线程数,另一个将填充最大异步I/O线程数)。
如果您想更好地了解应用程序在运行时发生的情况,可以使用Visual Studio 的线程窗口,方法是转到“调试”->“窗口”->“线程”(仅在调试时才会出现该条目,因此您需要首先在应用程序中设置断点)。 这篇文章可能会引起您的兴趣。似乎默认任务计划程序只是将任务排队到线程池的队列中,除非您使用TaskCreationOptions.LongRunning。这意味着由ThreadPool决定何时创建新线程。

TPL 不会使用线程池的所有线程,因为这样会使其他线程池用户饿死。我对默认任务调度程序的算法很感兴趣,该算法决定何时以及如何加入新线程。 - jgauffin
请查看默认任务调度程序的编辑。除非您使用LongRunning选项,否则它将使用线程池。我强烈建议您在调试时使用“线程”窗口来监视实际发生的情况。 - Neil Mountford
是的,但它不会直接将所有任务放在不同的线程池线程中,而是也可以将任务排队。我想知道它何时决定使用线程池,何时排队任务。 - jgauffin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接