Parallel.ForEach 行为

3
我知道使用Parallel.ForEach循环时,每个线程可能在任何给定时间执行循环的不同部分。但是,每个线程是否按顺序执行循环中的代码?我刚刚在"MSDN上的并行循环"上阅读到以下内容:

有时候,两个步骤的顺序与循环顺序相反。唯一的保证是在循环完成之前,所有的迭代都已经运行。

假设我有以下内容:
IEnumerable<MyObject> myEnumerable = ...
Parallel.ForEach(myEnumerable, obj =>
{
     A();
     B();
     C();
});

我知道线程1可能在执行A(),而线程2可能在执行C(),但是每个线程是否会按顺序执行循环中的代码?线程1是否会依次执行A() B() C(),还是可能会执行B()C()A()


15
每个线程将按照 A() -> B() -> C() 的顺序执行。 - Jonesopolis
6
Parallel.ForEach 不会分割 body 委托,它仅会分割可枚举对象。 - user4003407
谢谢!这正是我所想的,但措辞让我感到困惑。 - Dave
3个回答

8
一个迭代是整个循环体的一次单独执行,正如您在代码中所表达的那样。
这些迭代可以(并且很可能会)以任何顺序开始、运行和完成(这取决于实现细节和运行时数据,例如可用的工作进程和时间)。但是,每个单独的迭代都将被执行,就像循环是顺序的(就像普通的foreach),而不是并行的。
换句话说,它不可能对任何一个项目执行B(),然后执行C()再执行A()。对于每个项目,它总是先执行A(),然后执行B(),最后执行C()。您只是无法知道以什么顺序处理哪个项目。

0

Parallel.ForEach会为myEnumerable中的每个元素执行指定的委托。 例如:如果myEnumerable遍历了5个元素,那么序列A()、B()、C()将被调用5次(大多数情况下在并行线程中,但不能依赖于此)。不能保证所有线程都会同时执行A()方法来处理所有枚举元素,并且只有当所有线程中的所有A()方法完成后才开始执行B()方法(需要额外的同步才能实现此行为)。


0

正如你的问题评论中所述,Parallel.ForEach将按照你编写的顺序依次执行代码。

然而,你在msdn上读到的警告是指以下情况:

假设你有两个对象 a b,在迭代并行集合时,你必须确保对于每个迭代的对象,体内的步骤与其他迭代的对象独立

如果不是这样,最终的值可能与业务规则预期的不同。更糟糕的是,你可能永远不会知道它,因为可能没有错误(如果没有NullException或除零或任何其他错误发生)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接