Parallel.ForEach()
MaxDegreeOfParallelism==1
是否保证按顺序处理可枚举的输入?
如果答案是“否”,是否有办法强制执行此行为?
答案 0 :(得分:13)
首先,Microsoft's official documentation on parallel programming表明执行顺序无法保证是正确的。
Parallel.ForEach方法不保证执行顺序。与顺序ForEach循环不同,传入值不会按顺序处理。
最好使用Parallel.ForEach
作为公共API的设计:以并行方式处理项目。如果您需要按顺序处理项目,那么使用常规foreach
循环会更好。意图比使用MaxDegreeOfParallelism = 1
更清晰。
话虽如此,出于好奇,我看了一下.NET 4.7.1的源代码。简短的回答是是,如果MaxDegreeOfParallelism = 1
,将按顺序处理这些项目。但是,你不应该依赖它来进行未来的实现,因为它可能并不总是这样。
看一下Parallel.ForEach
并仔细阅读,你最终会看到要迭代的集合被分区(这个过程稍有不同,无论它是{{1} },TSource[]
或List<TSource>
。
IEnumerable<TSource>
和Task.SavedStateForNextReplica
在Task.SavedStateFromPreviousReplica
中被覆盖,以便在并行运行的任务之间传递状态。在这种情况下,它们用于通知任务应该迭代的分区。
最后,让我们来看看Task.ExecuteSelfReplicating
。 ParallelForReplicaTask
会根据指定的并行度以及任务计划程序ParallelForReplicatingTask
覆盖ShouldReplicate
。因此,使用MaximumConcurrencyLevel
只会创建一个子任务。因此,此任务仅在创建的单个分区上运行。
因此,要回答您的问题:撰写时,MaxDegreeOfParallelism = 1
与Parallel.ForEach
将枚举MaxDegreeOfParallism = 1
的集合from beginning to end,from beginning to end { {1}}和TSource[]
IList<TSource>
,路径略有不同,具体取决于IEnumerable<TSource>
是否可以投放到IEnumerable<TSource>
。这三条路径在use GetEnumerator
中确定。
我强烈建议您自己浏览源代码,亲眼看看。
我希望能够回答你的问题,但要记住这一点非常重要:不要依赖这个。这种实现很可能在将来发生变化。
答案 1 :(得分:3)
来自MSDN:
Parallel.ForEach方法不保证执行顺序。与顺序ForEach循环不同,传入值并不总是按顺序处理。