尽管线程池中有可用线程,但Task.Factory.StartNew的启动仍存在很大的延迟 [英] Task.Factory.StartNew starts with a great delay despite having available threads in threadpool
问题描述
此问题是我先前提出的问题的延续:
This question is a continuation to a previous question I've asked:
我现在知道如何精确地重现这种情况. Task.Factory.StartNew是在线程池上安排的,因此我正在记录以下内容(就在调用Factory.StartNew之前):
I now know how exactly to reproduce this scenario. Task.Factory.StartNew is scheduled on the thread pool, so I'm logging the following (just before I invoke the 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作为最大工作线程,32756作为可用工作线程.
When the bug is reproduced, I get 32767 as Max worker threads, and 32756 as available worker threads.
现在,有些事情我不理解. 至少据我了解,一旦线程池达到其过载,线程池将立即停止创建新线程.这可能是我的任务延迟的原因(从调用Factory.StartNew超过5秒后开始).
Now, there is something I don't understand. At least as I've understood, once the threadpool reaches its overload, the threadpool will stop creating new threads immediately. And that's probably the reason for the delay of my task (that starts after more than 5 seconds from the invocation of Factory.StartNew).
但是,当发生延迟时,我看到我的线程池中有32756个可用工作线程,那么为什么线程池不使用那些32756个可用工作线程之一立即启动我的任务?
But when the delay occurs, I see that I have 32756 available worker threads in my threadpool, so why does the threadpool NOT use one of those 32756 available worker threads to start my task immediately?
可用线程在ThreadPool上(我是说,我调用 ThreadPool .GetAvailableThreads),而Task.Factory.StartNew从threadPool分配任务.那么,为什么尽管线程池中有可用线程,但为什么会出现这种延迟?
The available threads are on the ThreadPool (I mean, I invoke ThreadPool.GetAvailableThreads), and Task.Factory.StartNew allocates a task from the threadPool. So, why am I getting this delay despite having available threads in threadpool?
推荐答案
It's not the MAX worker threads value you need to look at - it's the MIN value you get via ThreadPool.GetMinThreads()
.
最大值是可以活动的绝对最大线程数.最小值是始终保持活动状态的数字.如果您尝试在活动线程数小于最大数量(大于最小数量)时启动线程,则会看到2秒的延迟.
The max value is the absolute maximum threads that can be active. The min value is the number to always keep active. If you try to start a thread when the number of active threads is less than max (and greater than min) you'll see a 2 second delay.
如果绝对必要(在某些情况下是这种情况),您可以更改最小线程数,但是通常来说,如果发现自己需要这样做,则可能需要考虑重新设计多线程,这样就不需要
You can change the minimum number of threads if absolutely necessary (which it is in some circumstances) but generally speaking if you find yourself needing to do that, you might need to think about redesigning your multithreading so that you don't need to.