Parallel.ForEach行为

时间:2015-09-16 15:13:25

标签: c# multithreading parallel.foreach

我理解,使用Parallel.ForEach循环,每个线程可能在任何给定时间执行循环的不同部分。但是,每个线程是否按顺序执行循环中的代码?我刚刚阅读"Parallel Loops" on MSDN并说明:

  

有时,两个步骤的顺序与循环顺序时相反。唯一的保证是所有循环的迭代都将在循环结束时运行。

说我有以下内容:

IEnumerable<MyObject> myEnumerable = ...
Parallel.ForEach(myEnumerable, obj =>
{
     A();
     B();
     C();
});

我知道线程1可能正在执行A()而线程2可能正在执行C(),但每个线程将在循环中顺序执行代码。线程1是A() B() C()还是可能B()C()A()

3 个答案:

答案 0 :(得分:8)

迭代是整个循环体的单次执行,与代码中表达的完全相同。

迭代可以(并且很可能会)以任何顺序开始,运行和完成(这取决于实现细节和运行时数据,例如工作人员可用的时间和时间)。但是,仍然会执行每个单独的迭代,就好像循环是顺序的(如普通foreach)而不是并行。

换句话说,对于任何一个项目,它都不可能B()然后C()然后A()。对于每个项目,它始终会A()然后B()然后C()。您根本无法知道将以什么顺序处理哪个项

答案 1 :(得分:0)

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

答案 2 :(得分:0)

正如您对问题的评论中所述,Parallel.ForEach将按顺序执行您在主体中的代码。

但是,您在msdn上阅读的警告涉及以下情形:

假设您在并行迭代的集合中有两个对象ab。您必须确保对于您迭代的每个对象,正文中的步骤与任何其他迭代对象独立

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