尽管在线程池中有可用的线程,但Task.Factory.StartNew的启动时间很长
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尽管在线程池中有可用的线程,但Task.Factory.StartNew的启动时间很长相关的知识,希望对你有一定的参考价值。
这个问题是我提出的上一个问题的延续:
It takes more than a few seconds for a task to start running
我现在知道如何重现这种情况。 Task.Factory.StartNew是在线程池上安排的,所以我记录了以下内容(就在我调用Factory.StartNew之前):
int workerThreads = 0;
int completionPortThreads = 0;
ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
var tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
//I HAVE A LOG HERE
Task task = Task.Factory.StartNew(() =>
{
//I HAVE A LOG ALSO HERE, AND THAT'S HOW I KNOW,
//THE TASK INVOCATION IS DELAYED, AND THE DALAY IS NOT DUE TO MY CODE WITHIN THE TASK
// Some action that returns a boolean - **CODE_A**
}).ContinueWith((task2) =>
{
result= task2.Result;
if (!result)
{
//Another action **CODE_B**
}
}, token);
当错误被再现时,我获得32767作为Max工作线程,32756作为可用工作线程。
现在,有些事情我不明白。至少正如我所理解的,一旦线程池达到其重载,线程池将立即停止创建新线程。这可能是我的任务延迟的原因(从调用Factory.StartNew开始超过5秒后开始)。
但是当发生延迟时,我发现我的线程池中有32756个可用的工作线程,那么为什么线程池不使用这些32756可用工作线程中的一个来立即启动我的任务呢?
可用线程在ThreadPool上(我的意思是,我调用ThreadPool.GetAvailableThreads),Task.Factory.StartNew从threadPool中分配一个任务。那么,尽管在线程池中有可用的线程,为什么我会得到这个延迟?
这不是您需要查看的MAX工作线程值 - 它是您通过ThreadPool.GetMinThreads()
获得的MIN值。
最大值是可以激活的绝对最大线程数。最小值是始终保持活动的数字。如果在活动线程数小于max(且大于min)时尝试启动线程,则会看到2秒的延迟。
如果绝对必要,你可以改变最小线程数(在某些情况下是这样),但一般来说,如果你发现自己需要这样做,你可能需要考虑重新设计你的多线程,这样你就不需要了。
作为the Microsoft documentation states:
默认情况下,最小线程数设置为系统上的处理器数。您可以使用SetMinThreads方法来增加最小线程数。但是,不必要地增加这些值可能会导致性能问题。如果太多任务同时启动,则所有任务可能看起来都很慢。在大多数情况下,线程池将使用自己的算法来分配线程,从而表现更好。将最小值降低到小于处理器数量也会影响性能。
以上是关于尽管在线程池中有可用的线程,但Task.Factory.StartNew的启动时间很长的主要内容,如果未能解决你的问题,请参考以下文章