Parallel.ForEach 是否已过时。老了,过时了?

Is Parallel.ForEach obsolete. old, out of fashion?

美好的一天,

可以通过多种方式实现并行执行。从严格手动 "multithreading" 到使用 Microsoft 创建的各种 "helpers"。其中一个助手是 Parallel class。

我的一位同事坚持认为 Parallel.ForEach(或总体上的并行 class)是 "old",不应使用。相反,他说,人们应该使用异步操作。换句话说,您应该使用 Task.WhenAll() 而不是 Parallel.ForEach()

当被问到为什么不使用 Parallel.ForEach(), 而这正是所需要的 - 并行执行多个昂贵的操作 ,他回答说 Parallel.ForEach() 是旧的并且 Microsoft 建议尽可能使用 async/await。

我搜索了整个 MSDN 和 Whosebug 以及所有可能的地方,但我找不到任何指向使用 async/await 而不是 .Parallel 的必要性的信息。虽然您通常可以通过互换这些工具来获得类似的结果,但这并不意味着 Parallel.ForEach 已过时。或者是吗?

任何人都有一个 link 给一些 "best practices" 或 "recommendations" 的一个有信誉的机构(MSDN?),这会说 Parallel.ForEach() 正在被淘汰并且需要坚持创建、运行宁和等待任务?

请不要 post 回答与 Parallel VS Async 相关的问题,因为这不是问题所在。

问题是: 因为您可以使用 async/await WhenAllWaitAll 等)并行执行任务 运行 ),它是否使 'Parallel' class 在 .NET 4.5 之后过时、过时或不流行?

我不认为 Parallel.ForEach 已经过时。

自从在 .NET 4 中引入任务并行库 (TPL) 以来,Microsoft 已经 distinguished between "Data Parallelism" (e.g. Parallel.ForEach) and "Task Parallelism" (Task)。来自 MSDN:

  • "Data parallelism refers to scenarios in which the same operation is performed concurrently (that is, in parallel) on elements in a source collection or array."
  • "[T]ask parallelism refers to one or more independent tasks running concurrently."

(我强调。喜欢"Your friend is confusing parallelism with asynchrony."

这两类 parallelism/concurrency 追求不同的目标,因此 TPL 为他们提供了不同的能力。

从概念上讲,Task.WhenAll 属于任务并行性类别,因此我认为它不会淘汰属于其他(数据并行性)类别的内容。

Parallel.ForEach(以及整个 PLINQ)具有 async 语言支持所不具备的能力。

例如,您可以限制并行度(例如,要处理 100 个项目,但一次不要超过 10 个)。因此它并没有过时。

从根本上说 async 是为了让并发操作更容易编写——无需任何线程假设。 PLINQ 是关于利用多核的计算。

我怀疑您的同事对直接使用任务并行库 (TPL) 的阅读过多,这在很大程度上对于 async 语言来说是不必要的([=11= 的 return 类型除外] 职能)。但 PLINQ 始终是 TPL 之上的不同层。如果有的话,PLINQ 和 async 是将 TPL 用于不同目的的两种不同方式。

asyncawait 与并行性完全无关。它们是用于使现有异步 API 更易于使用和公开的技术。 asyncawait 不启动并行或并发。事实上 await 通过等待已经是 运行.

的东西来结束并行性

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

我认为你的同事不明白 await 真的只是等待。它没有启动任何东西。

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