是Parallel.ForEach已经过时了。过时了?

时间:2015-04-28 12:36:49

标签: multithreading design-patterns parallel-processing async-await .net-4.5

美好的一天,

并行执行可以通过多种方式实现。从严格的手动“多线程”到使用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 WhenAllWaitAll等)并行运行任务,是否会使“并行”类过时, .NET 4.5以后的旧版本,还是不时髦版本?

3 个答案:

答案 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)

asyncawait与并行性没有任何关系。它们是用于使现有异步API更易于使用和公开的技术。 asyncawait不会启动并行或并发。事实上, await通过等待已经投放的内容来结束并行性。

Parallel.ForEach用于在多个核心上以相同的方式处理一组同类项目。您可以通过生成大量任务来模拟Parallel.ForEach。这样做没有任何好处。实际上,它会导致效率低下并使代码混淆。如果Parallel.ForEach适用,它可能并且有效,但它是一种较差的做事方式。

我认为你的同事不明白等待真的等待。它没有开始。

使用Parallel。*和PLINQ(主要)进行CPU绑定工作。