WaitAll()未按预期执行

时间:2017-07-12 14:45:22

标签: c#-4.0 task

我已经编写了以下模拟代码作为我所看到的示例。我希望这些任务能够在一秒钟内完成,因为它们都等待一秒钟。相反,完成任务大约需要41秒。为什么它在41秒内完成而不是预期的~1秒?

Task[] tasks = new Task[1000];
DateTime startTime = DateTime.Now;
for (int i = 0; i < 1000; i++)
{
    // allocate room in the list for the items we are going to insert
    Task task = Task.Factory.StartNew(() => Thread.Sleep(1000));
    tasks[i] = task;
}
Task.WaitAll(tasks);
DateTime endTime = DateTime.Now;

TimeSpan span = endTime - startTime;

1 个答案:

答案 0 :(得分:0)

您的每个任务都被推送到线程池中,但这与为每个任务提供自己的线程并立即运行它并不是一回事。线程池不使用无限数量的线程,因为您没有无限数量的CPU核心。同时运行1000个线程通常会更慢,因为所有上下文切换都是因为许多线程争用少数可用内核。

相反,线程池尝试选择最佳线程数,以在保持所有内容移动和没有太多上下文切换之间取得平衡,从而使您获得最佳(或至少非常好)的吞吐量。每个运行1秒的1000个任务除以~40秒意味着池中有25个线程。

在这种情况下,您可以安全地运行更高的线程数,因为所有每个任务都是睡眠。但线程池并不知道。它期望你想用这些任务在CPU中做实际的实际工作,并且是相应的设计。即使在这里,请记住,即使只有25个线程,您已经有了完整的第二个开销。

最后,我经常运行使用这样的多个线程的代码来尝试在CPU上分配工作,结果发现真正的瓶颈是磁盘或网络I / O.总是值得提醒自己,您的磁盘速度非常快,如果您尝试分割来自文件,网络流或数据库的工作,您的CPU可能会快得多比你的数据源,如果有的话,你可能不会获得太多。这并不意味着停止&#34;但它确实意味着您还需要花时间来衡量,以确保这种额外的代码复杂性实际上是值得的。