美好的一天,
并行执行可以通过多种方式实现。从严格的手动“多线程”到使用Microsoft创建的各种“帮助者”。其中一个帮手是Parallel类。
我的一位同事坚持认为 Parallel.ForEach (或整体并行类)是“旧的”,不应该使用。相反,他说,应该使用异步操作。换句话说,您应该使用Task.WhenAll()
而不是Parallel.ForEach()
。
当被问到为什么不使用Parallel.ForEach(),
时,这正是所需要的 - 多个并行执行的昂贵操作,他回答说Parallel.ForEach()
已经过时且Microsoft建议使用async / await尽可能。
我搜遍了MSDN和Stackoverflow以及我能找到的任何地方,但我找不到任何指向使用async / await而不是.Parallel的必要性。虽然通常可以通过交换这些工具来获得类似的结果,但这并不意味着 Parallel.ForEach 已经过时了。或者是吗?
任何人都有一个信誉良好的机构(MSDN?)的某些“最佳做法”或“建议”的链接,它们会说Parallel.ForEach()
正在逐步淘汰,而且需要坚持创建,运行和等待任务?
请不要发布与并行VS异步相关的答案,因为这不是问题。
问题是:由于您可以使用async / await WhenAll
(WaitAll
等)并行运行任务,是否会使“并行”类过时, .NET 4.5以后的旧版本,还是不时髦版本?
答案 0 :(得分:5)
我认为Parallel.ForEach
已经过时了。
自从.NET 4引入任务并行库(TPL)以来,Microsoft已经distinguished between "Data Parallelism" (e.g. Parallel.ForEach
) and "Task Parallelism" (Task
)。来自MSDN:
- “数据并行性是指在源集合或数组中的元素上同时执行相同操作(即并行)的情况。”
- “[T]要求并行性是指一个或多个独立任务,并发。”
(由我强调。像dcastro commented (above):“你的朋友混淆了与异步的并行性。”)
这两种类型的并行/并发性追求不同的目标,因此TPL为每种目标提供不同的功能。
从概念上讲,Task.WhenAll
属于任务并行性类别,所以我认为它不会过时属于另一个(数据并行)类别的东西。
答案 1 :(得分:2)
Parallel.ForEach
(和PLINQ作为一个整体)具有async
语言支持中无法使用的功能。
例如,您可以限制并行度(例如,要处理的100个项目,但一次不要超过10个)。因此它不会过时。
基本上async
是关于进行并发操作 - 没有任何线程假设 - 更容易编写。 PLINQ是关于利用许多核心的计算。
我怀疑你的同事正在阅读太多关于直接使用任务并行库(TPL)在语言中async
基本上没有必要(除了async
函数的返回类型)。但PLINQ总是与TPL不同。如果PLINQ和async
是两种不同的方式,可以将TPL用于不同的目的。
答案 2 :(得分:2)
async
和await
与并行性没有任何关系。它们是用于使现有异步API更易于使用和公开的技术。 async
和await
不会启动并行或并发。事实上, await
通过等待已经投放的内容来结束并行性。
Parallel.ForEach
用于在多个核心上以相同的方式处理一组同类项目。您可以通过生成大量任务来模拟Parallel.ForEach
。这样做没有任何好处。实际上,它会导致效率低下并使代码混淆。如果Parallel.ForEach
适用,它可能并且有效,但它是一种较差的做事方式。
我认为你的同事不明白等待真的等待。它没有开始。
使用Parallel。*和PLINQ(主要)进行CPU绑定工作。