将MaxDegreeOfParallelism = 1进行Parallel.ForEach处理吗?

时间:2017-03-15 13:42:01

标签: c# .net parallel.foreach

Parallel.ForEach() MaxDegreeOfParallelism==1是否保证按顺序处理可枚举的输入?

如果答案是“否”,是否有办法强制执行此行为?

2 个答案:

答案 0 :(得分:13)

首先,Microsoft's official documentation on parallel programming表明执行顺序无法保证是正确的。

  

Parallel.ForEach方法不保证执行顺序。与顺序ForEach循环不同,传入值不会按顺序处理。

最好使用Parallel.ForEach作为公共API的设计:以并行方式处理项目。如果您需要按顺序处理项目,那么使用常规foreach循环会更好。意图比使用MaxDegreeOfParallelism = 1更清晰。

话虽如此,出于好奇,我看了一下.NET 4.7.1的源代码。简短的回答是是,如果MaxDegreeOfParallelism = 1 ,将按顺序处理这些项目。但是,你不应该依赖它来进行未来的实现,因为它可能并不总是这样。

  1. 看一下Parallel.ForEach并仔细阅读,你最终会看到要迭代的集合被分区(这个过程稍有不同,无论它是{{1} },TSource[]List<TSource>

  2. IEnumerable<TSource>Task.SavedStateForNextReplicaTask.SavedStateFromPreviousReplica中被覆盖,以便在并行运行的任务之间传递状态。在这种情况下,它们用于通知任务应该迭代的分区。

  3. 最后,让我们来看看Task.ExecuteSelfReplicatingParallelForReplicaTask会根据指定的并行度以及任务计划程序ParallelForReplicatingTask覆盖ShouldReplicate。因此,使用MaximumConcurrencyLevel只会创建一个子任务。因此,此任务仅在创建的单个分区上运行。

  4. 因此,要回答您的问题:撰写时,MaxDegreeOfParallelism = 1Parallel.ForEach将枚举MaxDegreeOfParallism = 1的集合from beginning to endfrom beginning to end { {1}}和TSource[] IList<TSource>,路径略有不同,具体取决于IEnumerable<TSource>是否可以投放到IEnumerable<TSource>。这三条路径在use GetEnumerator中确定。

    我强烈建议您自己浏览源代码,亲眼看看。

    我希望能够回答你的问题,但要记住这一点非常重要:不要依赖这个。这种实现很可能在将来发生变化。

答案 1 :(得分:3)

来自MSDN:

  

Parallel.ForEach方法不保证执行顺序。与顺序ForEach循环不同,传入值并不总是按顺序处理。

https://msdn.microsoft.com/library/ff963552.aspx