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


143

抱歉,我正在尝试使用Reflector在BCL中找到这两种方法,但找不到它们。这两个摘要有什么区别?

A:

IEnumerable<string> items = ...

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

B:

IEnumerable<string> items = ...

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

相互使用会产生不同的后果吗?(假设我在两个示例的方括号中所做的任何操作都是线程安全的。)

Answers:


148

他们做的事情完全不同。

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

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

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

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

简单地对computefibonacci进行并行foreach有什么好处?
l --''''''------------''''''''''''

51

区别在于,B不是平行的。唯一要做的AsParallel()是,它将包裹起来IEnumerable,以便在使用LINQ方法时使用它们的并行变体。包装器GetEnumerator()(在幕后使用foreach)甚至返回原始集合的结果GetEnumerator()

顺便说一句,如果您想查看Reflector中的方法,请在AsParallel()程序集中的 System.Linq.ParallelEnumerable类中System.CoreParallel.ForEach()mscorlib程序集中(名称空间System.Threading.Tasks)。


您是什么意思...使用了它们的并行变体...?
l --''''''------------''''''''''''

2
@punctuation例如,当您编写时.Select(),它会调用ParallelEnumerable.Select()而不是normal Enumerable.Select()
svick

50

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

IEnumerable<string> items = ...

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

3
为什么要结合使用asparallel和forall而不是简单地使用foreach?
l --''''''---------''''''''''''
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.