Parallel.ForEach 与 Task.Run 和 Task.WhenAll [英] Parallel.ForEach vs Task.Run and Task.WhenAll

查看:51
本文介绍了Parallel.ForEach 与 Task.Run 和 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆