Erg,我尝试使用 Reflector 在 BCL 中查找这两个方法,但找不到它们。这两个片段有什么区别?
答:
IEnumerable<string> items = ...
Parallel.ForEach(items, item => {
...
});
乙:
IEnumerable<string> items = ...
foreach (var item in items.AsParallel())
{
...
}
使用其中一种与另一种会有不同的后果吗? (假设我在两个示例的括号内所做的任何事情都是线程安全的。)
他们做的事情完全不同。
第一个采用匿名委托,并在此代码上针对所有不同的项目并行运行多个线程。
第二个在这种情况下不太有用。简而言之,它的目的是在多个线程上进行查询,然后组合结果,然后再次将其提供给调用线程。因此 foreach 语句上的代码始终保留在 UI 线程上。
只有当您在
AsParallel()
调用右侧的 linq 查询中执行一些昂贵的操作时才有意义,例如:
var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));
第二种方法不会并行,在您的示例中使用 AsParallel() 的正确方法是
IEnumerable<string> items = ...
items.AsParallel().ForAll(item =>
{
//Do parallel stuff here
});
不同之处在于,B 不平行。
AsParallel()
唯一做的就是它包裹了 IEnumerable
,因此当您使用 LINQ 方法时,会使用它们的并行变体。包装器的 GetEnumerator()
(在 foreach
的幕后使用)甚至返回原始集合的 GetEnumerator()
的结果。
顺便说一句,如果您想查看 Reflector 中的方法,
AsParallel()
位于 System.Linq.ParallelEnumerable
程序集中的 System.Core
类中。 Parallel.ForEach()
位于 mscorlib
程序集中(命名空间 System.Threading.Tasks
)。
这两个片段有什么区别?
第一个片段是并行的,第二个片段不是。
...
线程上并行调用
ThreadPool
代码,还包括当前线程作为工作线程之一。...
代码。枚举
items.AsParallel()
实际上与简单枚举 items
相同。以这种方式附加 AsParallel
PLINQ 运算符只会给阅读代码的人造成混乱。 AsParallel
旨在作为将更多 PLINQ 运算符附加到查询的起点。作为一个独立的运营商,它什么也不做。
来自文档:
并行枚举运算符 | 描述 |
---|---|
平行 | PLINQ 的入口点。指定查询的其余部分应该并行化(如果可能的话)。 |