Parallel.ForEach 会按照 MaxDegreeOfParallelism=1 的顺序进行处理吗?
Posted
技术标签:
【中文标题】Parallel.ForEach 会按照 MaxDegreeOfParallelism=1 的顺序进行处理吗?【英文标题】:Will Parallel.ForEach process in order with MaxDegreeOfParallelism=1? 【发布时间】:2017-08-06 07:08:02 【问题描述】:Parallel.ForEach()
和 MaxDegreeOfParallelism==1
是否保证按顺序处理输入可枚举?
如果答案是“否”,有没有办法强制执行这种行为?
【问题讨论】:
我能问一下你为什么想知道这个吗?只是学术好奇心,还是您遇到了某种现实问题? @mituw16:我在链接的 MSDN 文章中找不到任何提示。进行一些测试也不能保证“是”。 这样的问题取决于实现细节,如果 msdn 没有说明,将来可以更改。你需要按顺序运行吗?然后使用Queue<>
。
如果您的测试代码需要按顺序处理实际情况下不按顺序排列的内容,那么您的测试就有缺陷。重写它以便验证结果不依赖于这个假设,或者重写被测代码以在 MaxDegreeOfParallelism
为 1 时产生显式异常,这样您就可以确保它在所有情况下的行为一致。显然,第一个选项更可取。
@l33t - 查看源代码或运行测试不会告诉您有关未来实现的任何信息。您需要文档中的 explicit 语句。
【参考方案1】:
首先,Microsoft's official documentation on parallel programming 声明执行顺序无法保证是正确的。
Parallel.ForEach 方法不保证执行顺序。与顺序 ForEach 循环不同,传入的值并不总是按顺序处理。
最好使用Parallel.ForEach
,因为公共 API 的设计目的是:以并行方式处理项目。如果您需要按顺序处理项目,最好使用常规的foreach
循环。意图比使用MaxDegreeOfParallelism = 1
更清晰。
话虽如此,出于好奇,我查看了 .NET 4.7.1 的源代码。简短的回答是是的,如果MaxDegreeOfParallelism = 1
,项目将按顺序处理。但是,您不应该在未来的实现中依赖它,因为它可能并不总是这样。
看一下Parallel.ForEach
,然后继续看下去,你最终会看到要迭代的集合是分区的(这个过程有点不同,不管是TSource[]
,List<TSource>
,或IEnumerable<TSource>
。
Task.SavedStateForNextReplica
和 Task.SavedStateFromPreviousReplica
在 ParallelForReplicaTask
中被覆盖,以便在并行运行的任务之间传达状态。在这种情况下,它们用于传达任务应该迭代哪个分区。
最后,我们来看看Task.ExecuteSelfReplicating
。 ParallelForReplicatingTask
根据指定的并行度以及任务调度程序的 MaximumConcurrencyLevel
覆盖 ShouldReplicate
。所以,MaxDegreeOfParallelism = 1
只会创建一个子任务。因此,此任务将仅在创建的单个分区上运行。
所以,为了回答您的问题:在撰写本文时,Parallel.ForEach
和 MaxDegreeOfParallism = 1
将枚举集合 from beginning to end 为 TSource[]
,from beginning to end 为 IList<TSource>
,use GetEnumerator
为 @ 987654349@,路径略有不同,具体取决于 IEnumerable<TSource>
是否可以转换为 OrderablePartitioner<TSource>
。这三个路径在Parallel.ForEachWorker
中确定。
我强烈建议您自行浏览源代码以亲自查看。
我希望这能够回答你的问题,但记住这一点非常重要:不要依赖这个。这种实现很有可能在未来发生变化。
【讨论】:
【参考方案2】:来自 MSDN:
Parallel.ForEach 方法不保证执行顺序。与顺序 ForEach 循环不同,传入的值并不总是按顺序处理。
https://msdn.microsoft.com/library/ff963552.aspx
【讨论】:
以上是关于Parallel.ForEach 会按照 MaxDegreeOfParallelism=1 的顺序进行处理吗?的主要内容,如果未能解决你的问题,请参考以下文章