已创建的1000个任务中,假设taskCompletionSource在代码的其他部分中成功完成,则只有很少(10)个任务可以完成。这意味着ProcessWorkItemAsync
完成仅将被打印10次。
代码:
for (var i = 0;i<1000; i++)
{
Task.Run(() => {
await ProcessWorkItemAsync();
Console.WriteLine("ProcessWorkItemAsync finished");
});
}
async Task<TaskCompletionSource<int>> ProcessWorkItemAsync()
{
return new TaskCompletionSource<int>();
}
答案 0 :(得分:4)
已创建的1000个任务中,假设taskCompletionSource在代码的其他部分中成功完成,则只有很少(10)个任务可以完成。这意味着ProcessWorkItemAsync完成仅将打印10次。
您发布的代码没有该行为。发布的代码将打印"ProcessWorkItemAsync finished"
1000次,所有任务几乎立即完成。对于此答案的其余部分,我将解决问题并忽略代码。
是否有990项CPU开销未完成且处于困境?
否。
从我所读的内容来看,线程不会被阻塞,它将返回到线程池,因此从CPU的角度看,似乎没有任何开销。我还缺少其他东西吗?
任务不是线程。您实际上没有1000个任务的事实意味着有或曾经有1000个线程。
Task.Run
确实将工作加到线程池中,但是将异步任务与Task.Run
一起使用时,只要await
必须异步等待,该线程池中的线程就会返回到线程池中。任务是否完成无关紧要。
有内存开销吗?
是的。任务是对象,就像其他任何引用类型一样。它们可以像其他引用类型一样扎根。而且,如果从未清除(完成)它们,则它们可以像其他任何引用类型一样a resource leak。
因为要存储调用堆栈,所以点网必须跟踪返回的位置。我假设这些调用堆栈将存储在堆中并产生内存消耗?
排序。不会捕获或存储调用堆栈。该任务仅存储其继续。从逻辑上讲,您可以将其视为“调用堆栈”,但深度只有1。因此,每个任务将使await
使用它的所有代码保持有效。