我理解,使用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()
?
答案 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上阅读的警告涉及以下情形:
假设您在并行迭代的集合中有两个对象a
和b
。您必须确保对于您迭代的每个对象,正文中的步骤与任何其他迭代对象独立。
如果不是,值可能不是最终业务规则的预期值。 更糟糕的是,您可能永远不会知道,因为可能没有错误(如果没有NullException或除零或发生任何其他错误)。