Parallel.ForEach() 与 foreach(IEnumerable<T>.AsParallel())
Posted
技术标签:
【中文标题】Parallel.ForEach() 与 foreach(IEnumerable<T>.AsParallel())【英文标题】:Parallel.ForEach() vs. foreach(IEnumerable<T>.AsParallel()) 【发布时间】:2011-04-16 22:36:38 【问题描述】:呃,我正在尝试使用 Reflector 在 BCL 中找到这两种方法,但找不到它们。这两个sn-ps有什么区别?
答:
IEnumerable<string> items = ...
Parallel.ForEach(items, item =>
...
);
乙:
IEnumerable<string> items = ...
foreach (var item in items.AsParallel())
...
使用其中一种会有不同的后果吗? (假设我在两个示例的括号中所做的任何事情都是线程安全的。)
【问题讨论】:
【参考方案1】:他们做的事情完全不同。
第一个接受匿名委托,并在此代码上为所有不同的项目并行运行多个线程。
第二个在这种情况下不是很有用。简而言之,它旨在对多个线程进行查询,并将结果组合起来,然后再次将其提供给调用线程。因此,foreach 语句中的代码始终保留在 UI 线程上。
只有在 AsParallel()
调用右侧的 linq 查询中执行昂贵的操作时才有意义,例如:
var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));
【讨论】:
与简单地在 computefibonacci 上执行并行 foreach 相比有什么好处?【参考方案2】:第二种方法不会并行,在您的示例中使用 AsParallel() 的正确方法是
IEnumerable<string> items = ...
items.AsParallel().ForAll(item =>
//Do parallel stuff here
);
【讨论】:
为什么要结合使用 asparallel 和 forall 而不是简单的 foreach?【参考方案3】:不同的是,B 不是平行的。 AsParallel()
所做的唯一事情是它包裹了 IEnumerable
,因此当您使用 LINQ 方法时,会使用它们的并行变体。包装器的GetEnumerator()
(在foreach
的幕后使用)甚至返回原始集合的GetEnumerator()
的结果。
顺便说一句,如果您想查看 Reflector 中的方法,AsParallel()
在 System.Core
程序集中的 System.Linq.ParallelEnumerable
类中。 Parallel.ForEach()
在 mscorlib
程序集中(命名空间 System.Threading.Tasks
)。
【讨论】:
你的意思是……他们的平行变种被使用了……? @punctuation 例如,当您编写.Select()
时,它调用ParallelEnumerable.Select()
而不是正常的Enumerable.Select()
。以上是关于Parallel.ForEach() 与 foreach(IEnumerable<T>.AsParallel())的主要内容,如果未能解决你的问题,请参考以下文章
Parallel.ForEach 与 Task.Factory.StartNew
Task.StartNew() 与 Parallel.ForEach :多个 Web 请求场景
在 .NET 3.5 中将 Parallel.Foreach 与分区器一起使用
Asp.Net 中有没有办法与运行 Parallel.Foreach 的后台线程进行通信