Parallel.ForEach 与 Task.Run 和 Task.WhenAll [英] Parallel.ForEach vs Task.Run and Task.WhenAll
问题描述
使用 Parallel.ForEach 或 Task.Run() 异步启动一组任务有什么区别?
What are the differences between using Parallel.ForEach or Task.Run() to start a set of tasks asynchronously?
版本 1:
List<string> strings = new List<string> { "s1", "s2", "s3" };
Parallel.ForEach(strings, s =>
{
DoSomething(s);
});
版本 2:
List<string> strings = new List<string> { "s1", "s2", "s3" };
List<Task> Tasks = new List<Task>();
foreach (var s in strings)
{
Tasks.Add(Task.Run(() => DoSomething(s)));
}
await Task.WhenAll(Tasks);
推荐答案
这种情况下,第二种方法会异步等待任务完成而不是阻塞.
In this case, the second method will asynchronously wait for the tasks to complete instead of blocking.
但是,在循环中使用 Task.Run
有一个缺点——使用 Parallel.ForEach
,有一个 Partitioner
创建它是为了避免执行不必要的任务.Task.Run
将始终为每个项目创建一个任务(因为您正在执行此操作),但是 Parallel
类可以批处理工作,因此您创建的任务少于总工作项目.这可以显着提高整体性能,尤其是当循环体每个项目的工作量很少时.
However, there is a disadvantage to use Task.Run
in a loop- With Parallel.ForEach
, there is a Partitioner
which gets created to avoid making more tasks than necessary. Task.Run
will always make a single task per item (since you're doing this), but the Parallel
class batches work so you create fewer tasks than total work items. This can provide significantly better overall performance, especially if the loop body has a small amount of work per item.
如果是这种情况,您可以通过以下方式组合两个选项:
If this is the case, you can combine both options by writing:
await Task.Run(() => Parallel.ForEach(strings, s =>
{
DoSomething(s);
}));
请注意,这也可以写成更短的形式:
Note that this can also be written in this shorter form:
await Task.Run(() => Parallel.ForEach(strings, DoSomething));
这篇关于Parallel.ForEach 与 Task.Run 和 Task.WhenAll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!