订购PLINQ ForAll

Ste*_*ris 11 c# plinq

关于PLINQ中的订单保存的msdn文档说明了以下内容ForAll().

  • 订购源序列时的结果:并行执行非确定性
  • 源序列无序时的结果:并行执行非确定性

这是否意味着ForAll永远不能保证该方法的有序执行?

我以前没有使用PLINQ,但以下Code Review问题似乎是适合它的用法.在我的回答的底部,我写道:

Events.AsParallel().AsOrdered().ForAll( eventItem =>
{
    ...
} );    
Run Code Online (Sandbox Code Playgroud)

阅读文档后,我相信AsOrdered()不会改变任何东西?
我也怀疑以前的查询不能取代for顺序很重要的简单循环?
可能StringBuilder会发生与意志的并行调用,导致输出错误?

Jon*_*eet 15

订单保留通常仅适用于结果 - 即输入可以按任何顺序处理,但以原始顺序返回.

由于ForAll没有返回任何东西,它实际上没有任何我所知道的效果.

处理进行排序的唯一方法是在处理第1项之前,在处理第2项之前完成第0项......此时你没有并行性.

  • 史蒂文:您可以使用PLINQ进行解析,使其按顺序给出结果,并使用正常的foreach循环来进行实际追加. (2认同)

Fan*_*rns 7

正如其他人正确回答的那样,该ForAll方法永远不能保证以任何特定顺序对可枚举元素执行操作,并且将以AsOrdered()静默方式忽略方法调用.

为了使读者有充分的理由以一种与原始顺序保持一致的方式执行可枚举元素的操作(在并行处理上下文中是合理的),下面的扩展方法可能有所帮助.

public static void ForAllInApproximateOrder<TSource>(this ParallelQuery<TSource> source, Action<TSource> action) {

    Partitioner.Create( source )
               .AsParallel()
               .AsOrdered()
               .ForAll( e => action( e ) );

}
Run Code Online (Sandbox Code Playgroud)

然后可以按如下方式使用:

orderedElements.AsParallel()
               .ForAllInApproximateOrder( e => DoSomething( e ) );
Run Code Online (Sandbox Code Playgroud)

应该注意的是,上面的扩展方法使用PLINQ ForAll而不是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 ) );

}
Run Code Online (Sandbox Code Playgroud)

然后可以按如下方式使用:

orderedElements.AsParallel()
               .ForEachInApproximateOrder( e => DoSomething( e ) );
Run Code Online (Sandbox Code Playgroud)

AsOrdered()使用上述任何一种扩展方法时,无需链接到您的查询,无论如何都会在内部调用它.

我发现这些方法可用于处理具有粗粒度重要性的元素.例如,处理从最旧的开始并向最新的方向工作的记录可能是有用的.在许多情况下,不需要记录的确切顺序 - 只要较旧的记录通常在较新的记录之前得到处理.类似地,可以处理具有低/中/高优先级的记录,使得在大多数情况下优先级较低的记录之前处理高优先级记录,边缘情况不远.


Bro*_*ass 5

AsOrdered()不会改变任何东西 - 如果你想对并行查询的结果强制执行顺序,你可以简单地使用foreach() ForAll()它来利用并行性,这意味着一次对集合中的多个项目执行副作用.实际上,排序仅适用于查询的结果(结果集合中的项目顺序),但这与此无关ForAll(),因为ForAll()它根本不会影响订单.

在PLINQ中,目标是在保持正确性的同时最大化性能.查询应尽可能快地运行,但仍会产生正确的结果.在某些情况下,正确性要求保留源序列的顺序

请注意,这ForAll()不是转换集合(它不是投影到新集合),它纯粹是为了对PLINQ查询的结果执行副作用.