使用AsSequential以保持顺序。

10

我正在查看这段代码

var numbers = Enumerable.Range(0, 20);
var parallelResult = numbers.AsParallel().AsOrdered()
    .Where(i => i % 2 == 0).AsSequential();

foreach (int i in parallelResult.Take(5))
    Console.WriteLine(i);

AsSequential()应该使结果数组排序。实际上,它在执行后被排序,但是如果我删除对AsSequential()的调用,则仍然会进行排序(因为调用了AsOrdered())。

这两者之间有什么区别?


这个例子在书中没有使用.ToArray(),因此也没有所谓的“结果数组”(我猜你指的是《C#编程考试参考70-483》)。 - comecme
2个回答

12

AsSequential 的作用是停止进一步的并行执行,因此得名。我不确定您从何处得到它“应该使生成的数组排序”的想法。 文档 非常清楚:

将 ParallelQuery 转换为 IEnumerable,以强制对查询进行顺序评估。

正如您所说,AsOrdered 确保该特定序列的排序。


我所提到的书中写道:“如果您有一个复杂的查询可以从并行处理中受益,但也有一些部分应该按顺序完成,您可以使用AsSequential来阻止查询被并行处理。其中需要这样做的一个场景是保留查询的排序。清单1-25展示了如何使用AsSequential运算符确保Take方法不会破坏您的顺序。”我查看了您提供的链接,您说得完全正确。 - MaPi
@user1648371:听起来像是书中的问题,没错。 - Jon Skeet
规格说明指出,AsSequential用于保留前面子句建立的顺序。它只适用于 SQL 查询吗?规格说明还指出,Take将无法利用并行处理运行时。那么是本书有误还是其他原因?我感到困惑。 - comecme
@comecme:看这个例子——排序是通过 OrderBy 调用建立的。AsSequential 保留了该顺序,但并不像原问题所声称的那样“使得结果数组排序”。保留现有顺序和强制特定顺序之间存在很大的区别。 - Jon Skeet
@JonSkeet:如果OP正在阅读我正在阅读的书,那么这本书并没有真正说明AsSequential会对结果进行排序。它声明将保留顺序。这也是关于AsSequential的规范所说的。因此,如果省略AsSequential,问题仍然存在,即为什么结果仍然相同。 - comecme
1
@comecme:好吧,我在回答问题 :) 但如果我有时间,晚些时候我会扩展答案。 - Jon Skeet

2

我知道这个问题已经过去一年了,但是我想提出我的意见。

在这个示例中,我认为它使用AsSequential,以便下一个查询运算符(在这种情况下是Take运算符)按顺序执行。

然而,除非源元素处于其原始索引位置,否则Take运算符会阻止查询并行化,这就是为什么即使您删除AsSequential运算符,结果仍然是排序的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接