此问题是我先前提出的问题的延续:
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作为最大工作线程,32756作为可用工作线程。
现在,有些事情我不理解。 至少据我了解,一旦线程池达到其过载,线程池将立即停止创建新线程。这可能是我的任务延迟的原因(从调用Factory.StartNew超过5秒后开始)。
但是当延迟发生时,我看到我的线程池中有32756个可用工作线程,那么为什么线程池不使用那些32756个可用工作线程之一立即启动我的任务?
可用线程在ThreadPool上(我是说,我调用 ThreadPool .GetAvailableThreads),而Task.Factory.StartNew从threadPool分配任务。那么,为什么尽管线程池中有可用线程,但为什么会出现这种延迟?
答案 0 :(得分:3)
这不是您需要查看的MAX工作线程值,而是您通过ThreadPool.GetMinThreads()
获得的MIN值。
最大值是可以活动的绝对最大线程数。最小值是始终保持活动状态的数字。如果您尝试在活动线程数小于最大数量(且大于最小数量)时启动线程,则会看到2秒的延迟。
如果绝对必要(在某些情况下是这样),您可以更改最小线程数,但通常来说,如果发现自己需要这样做,则可能需要考虑重新设计多线程,这样就不需要
为the Microsoft documentation states:
默认情况下,最小线程数设置为系统上的处理器数。您可以使用SetMinThreads方法来增加最小线程数。但是,不必要地增加这些值可能会导致性能问题。如果太多任务同时开始,则它们似乎都变慢了。在大多数情况下,线程池使用自己的分配线程算法会更好地执行。将最小值降低到少于处理器数量也会损害性能。