正如其他人正确回答的那样,该ForAll
方法永远不能保证以任何特定顺序对可枚举元素执行操作,并且会AsOrdered()
默默地忽略方法调用。
为了读者有正当理由以接近原始顺序的方式执行可枚举元素的操作(只要在并行处理上下文中合理),下面的扩展方法可能会有所帮助。
public static void ForAllInApproximateOrder<TSource>(this ParallelQuery<TSource> source, Action<TSource> action) {
Partitioner.Create( source )
.AsParallel()
.AsOrdered()
.ForAll( e => action( e ) );
}
然后可以按如下方式使用:
orderedElements.AsParallel()
.ForAllInApproximateOrder( e => DoSomething( e ) );
应该注意的是,上面的扩展方法使用 PLINQForAll
而不是Parallel.ForEach
,因此继承了 PLINQ 内部使用的线程模型(这与Parallel.ForEach
我使用的不同——默认情况下不那么激进)。类似的扩展方法使用Parallel.ForEach
如下。
public static void ForEachInApproximateOrder<TSource>(this ParallelQuery<TSource> source, Action<TSource> action) {
source = Partitioner.Create( source )
.AsParallel()
.AsOrdered();
Parallel.ForEach( source , e => action( e ) );
}
然后可以按如下方式使用:
orderedElements.AsParallel()
.ForEachInApproximateOrder( e => DoSomething( e ) );
AsOrdered()
使用上述任一扩展方法时,无需链接到您的查询,无论如何它都会在内部调用。
我发现这些方法在处理具有粗粒度意义的元素时很有用。例如,它可以用于处理从最旧开始到最新的记录。在许多情况下,不需要记录的确切顺序 - 只要较旧的记录通常在较新的记录之前得到处理。类似地,可以处理具有低/中/高优先级的记录,以便在大多数情况下,高优先级记录将在低优先级记录之前处理,边缘情况紧随其后。