c# - Parallel.ForEach 会按照 MaxDegreeOfParallelism=1 的顺序进行处理吗?

标签 c# .net parallel.foreach

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

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

最佳答案

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

The Parallel.ForEach method does not guarantee the order of execution. Unlike a sequential ForEach loop, the incoming values aren't always processed in order.

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

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

  1. 查看 Parallel.ForEach 并按照它完成,您最终会看到要迭代的集合已分区(此过程略有不同,无论是 TSource[]List<TSource> 还是 IEnumerable<TSource>

  2. Task.SavedStateForNextReplicaTask.SavedStateFromPreviousReplicaParallelForReplicaTask 中被覆盖为了在并行运行的任务之间传递状态。在这种情况下,它们用于传达任务应该遍历哪个分区。

  3. 最后,我们来看看 Task.ExecuteSelfReplicating . ParallelForReplicatingTask覆盖 ShouldReplicate基于指定的并行度以及任务调度程序的 MaximumConcurrencyLevel .所以,这与 MaxDegreeOfParallelism = 1只会创建一个子任务。因此,此任务将仅对创建的单个分区进行操作。

因此,回答您的问题:截至撰写本文时,Parallel.ForEachMaxDegreeOfParallism = 1将枚举集合 from beginning to end对于 TSource[] , from beginning to end对于 IList<TSource> , 和 use GetEnumerator 对于 IEnumerable<TSource> ,路径略有不同,具体取决于 IEnumerable<TSource> 是否可以转换为 OrderablePartitioner<TSource>或不。这三个路径在 Parallel.ForEachWorker 中确定.

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

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

关于c# - Parallel.ForEach 会按照 MaxDegreeOfParallelism=1 的顺序进行处理吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42811544/

相关文章:

c# - 关于.Net运行时

c# - 在 Visual Studio 中给定一个类,如何找出包含它的 dll?

c# - 从反射树切换到表达式树

c# - 如何使用Ninject 3在MVC 5中创建消息传递系统?

c# - Ghostscript.NET 无法使用选定的打印机名称进行打印

c# - 在 Windows 应用商店应用中放大图像

c# - Parallel.ForEach 性能不佳

c# - 验证定制的 SMTP 服务器

c# - 从列表中选择不同数量的项目组合

c# - SerialPort.ReadTo() 上的 ArgumentOutOfRangeException