【发布时间】:2018-12-03 08:15:34
【问题描述】:
这个问题是我上一个问题的延续:
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);
当 bug 重现时,我得到 32767 作为 Max 工作线程,32756 作为可用工作线程。
现在,有些东西我不明白。 至少据我了解,一旦线程池达到过载,线程池将立即停止创建新线程。这可能是我的任务延迟的原因(从调用 Factory.StartNew 开始超过 5 秒后开始)。
但是当延迟发生时,我看到我的线程池中有 32756 个可用的工作线程,那么为什么线程池不使用这 32756 个可用的工作线程之一来立即启动我的任务?
可用线程在 ThreadPool 上(我的意思是,我调用 ThreadPool.GetAvailableThreads),Task.Factory.StartNew 从 threadPool 分配一个任务。那么,尽管线程池中有可用线程,为什么我会出现这种延迟?
【问题讨论】:
-
你的代码是做什么的,为什么你认为是 StartNew 慢而不是说,代码本身?您是否尝试过分析代码?只需在调试期间暂停并检查
Parallel Stacks窗口。它显示了什么?你是在要求人们猜测。可以肯定的是,线程池并不慢,除非您用任务淹没 CPU,将所有可用时间浪费在线程切换上。毕竟,你不能同时运行的线程数超过逻辑核心数 -
@Panagiotis Kanavos 我肯定知道,因为我在调用 StartNew 之前和开始时有一个日志,甚至在我的代码运行之前(任务中的代码)。跨度>
-
@DimaK 所以你根本不知道。你在假设。我们甚至不能这样做,因为您还没有发布任何内容。 你无法知道这是代码的错,因为你没有检查还有多少其他任务。发布您的代码,或使用并行调试窗口检查延迟发生时发生的情况。
-
这不是您需要查看的 MAX 工作线程值 - 这是您通过
ThreadPool.GetMinThreads()获得的 MIN 值。最大值是可以活动的绝对最大线程数。最小值是始终保持活动状态的数字。如果您尝试在活动线程数小于最大值(且大于最小值)时启动线程,您将看到 2 秒延迟。
标签: c# multithreading task