Parallel.ForEach() 与 foreach(IEnumerable<T>.AsParallel())

问题描述 投票:0回答:4

Erg,我尝试使用 Reflector 在 BCL 中查找这两个方法,但找不到它们。这两个片段有什么区别?

答:

IEnumerable<string> items = ...

Parallel.ForEach(items, item => {
   ...
});

乙:

IEnumerable<string> items = ...

foreach (var item in items.AsParallel())
{
   ...
}

使用其中一种与另一种会有不同的后果吗? (假设我在两个示例的括号内所做的任何事情都是线程安全的。)

c# multithreading parallel-processing parallel.foreach plinq
4个回答
156
投票

他们做的事情完全不同。

第一个采用匿名委托,并在此代码上针对所有不同的项目并行运行多个线程。

第二个在这种情况下不太有用。简而言之,它的目的是在多个线程上进行查询,然后组合结果,然后再次将其提供给调用线程。因此 foreach 语句上的代码始终保留在 UI 线程上。

只有当您在

AsParallel()
调用右侧的 linq 查询中执行一些昂贵的操作时才有意义,例如:

 var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));

59
投票

第二种方法不会并行,在您的示例中使用 AsParallel() 的正确方法是

IEnumerable<string> items = ...

items.AsParallel().ForAll(item =>
{
    //Do parallel stuff here
});

55
投票

不同之处在于,B 不平行。

AsParallel()
唯一做的就是它包裹了
IEnumerable
,因此当您使用 LINQ 方法时,会使用它们的并行变体。包装器的
GetEnumerator()
(在
foreach
的幕后使用)甚至返回原始集合的
GetEnumerator()
的结果。

顺便说一句,如果您想查看 Reflector 中的方法,

AsParallel()
位于
System.Linq.ParallelEnumerable
程序集中的
System.Core
类中。
Parallel.ForEach()
位于
mscorlib
程序集中(命名空间
System.Threading.Tasks
)。


0
投票

这两个片段有什么区别?

第一个片段是并行的,第二个片段不是。

  1. 第一个代码片段在多个
    ...
     线程上并行调用 
    ThreadPool
    代码,还包括当前线程作为工作线程之一。
  2. 第二个片段仅在当前线程上顺序调用
    ...
    代码。

枚举

items.AsParallel()
实际上与简单枚举
items
相同。以这种方式附加
AsParallel
PLINQ 运算符只会给阅读代码的人造成混乱。
AsParallel
旨在作为将更多 PLINQ 运算符附加到查询的起点。作为一个独立的运营商,它什么也不做。

来自文档

并行枚举运算符 描述
平行 PLINQ 的入口点。指定查询的其余部分应该并行化(如果可能的话)。
© www.soinside.com 2019 - 2024. All rights reserved.