我正在尝试理解
看起来第二种情况的性能要好得多。 我知道使用
在分析系统流程后,我认为已经找到了如何在简单的测试应用程序中对问题进行建模(测试代码基于I3arnon的答案)。
WaitAll
和WhenAll
的工作原理,并遇到以下问题。 有两种可能的方法可以从方法中获取结果:
return Task.WhenAll(tasks).Result.SelectMany(r=> r);
return tasks.Select(t => t.Result).SelectMany(r => r).ToArray();
tasks
上调用WaitAll
,然后在此之后获取结果。看起来第二种情况的性能要好得多。 我知道使用
await
关键字是使用WhenAll
的正确方式,但我仍然想知道为什么这些行的性能差异如此之大。在分析系统流程后,我认为已经找到了如何在简单的测试应用程序中对问题进行建模(测试代码基于I3arnon的答案)。
public static void Test()
{
var tasks = Enumerable.Range(1, 1000).Select(n => Task.Run(() => Compute(n)));
var baseTasks = new Task[100];
var stopwatch = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
baseTasks[i] = Task.Run(() =>
{
tasks.Select(t => t.Result).SelectMany(r => r).ToList();
});
}
Task.WaitAll(baseTasks);
Console.WriteLine("Select - {0}", stopwatch.Elapsed);
baseTasks = new Task[100];
stopwatch.Restart();
for (int i = 0; i < 100; i++)
{
baseTasks[i] = Task.Run(() =>
{
Task.WhenAll(tasks).Result.SelectMany(result => result).ToList();
});
}
Task.WaitAll(baseTasks);
Console.WriteLine("Task.WhenAll - {0}", stopwatch.Elapsed);
}
看起来问题出在从其他任务(或Parallel
循环)启动任务上。在这种情况下,WhenAll
会导致程序的性能大大降低。为什么会这样呢?
IEnumerable
时才会被评估。你确定你的任务已经开始了吗? - DennisToArray
,因此它不会有延迟执行。 - Richard SzalayParallel.ForEach
与Task
结合使用并不是我推荐的做法。如果可以,请使用Parallel.ForEach
来最大化性能,但如果不可能并且必须启动Task
,那么在一个高度优化和分区的并行循环中这样做是没有意义的。 - Martin Liversage