Parallel.Foreach维护收集顺序?

时间:2010-11-09 16:31:17

标签: asp.net-4.0 parallel-processing task-parallel-library parallel-for

使用Parallel.ForEach()时有办法保证订单吗?我正在循环的集合需要保持它的顺序,但我正在寻找一些性能改进。

5 个答案:

答案 0 :(得分:6)

所以你有一个看起来像这样的陈述? (根据您的上述评论)。

Parallel.Foreach(myData, ..., (d) =>
{
  StringBuilder sb = new StringBuilder();
  sb.Append(d);
  // WriteLine sb?
});

这种方法存在许多问题。

  1. Parallel.ForParallel.ForEach都不会保证您以任何特定顺序访问myData的内容。
  2. 如果您是控制台上的方法或共享StringBuilder 要么输出结果,要么建立一个完整的字符串 可能是在共享资源上阻塞,有效地序列化 并行循环的一部分。
  3. 如果没有看到代码的具体示例,很难说更多。根据您的工作情况,您可以使用PLINQ中的订单保存AsOrdered()来获取您想要的位置。
    请参阅this MSDN ResourceOrdered PLINQ ForAll

    这将允许您根据输入顺序返回有序的结果集,但保证实际处理的顺序。 但是,如果并行查询阻塞了正文中的调用,则不太可能获得良好的性能。

答案 1 :(得分:3)

为了保留订单,您必须先尝试在将列表传递给foreach循环之前对其进行排序,因为默认情况下Parallel.Foreach会将列表视为无序。

示例:

Parallel.ForEach(
list.AsParallel().AsOrdered(), 
(listItems) => {<operations that you need to do>});

答案 2 :(得分:0)

对于任何寻找简单解决方案的人,我发布了2个扩展方法(一个使用PLINQ,另一个使用Parallel.ForEach)作为以下问题答案的一部分:

Ordered PLINQ ForAll

答案 3 :(得分:0)

将此作为扩展方法

 public static IEnumerable<T1> OrderedParallel<T, T1>(this IEnumerable<T> list, Func<T, T1> action)
    {
        var unorderedResult = new ConcurrentBag<(long, T1)>();
        Parallel.ForEach(list, (o, state, i) =>
        {
            unorderedResult.Add((i, action.Invoke(o)));
        });
        var ordered = unorderedResult.OrderBy(o => o.Item1);
        return ordered.Select(o => o.Item2);
    }

使用方式:

var result = input.OrderedParallel(o => YourFunction(o));

希望这可以为您节省一些时间。

答案 4 :(得分:-1)

不,ForEach仅用于订单无关紧要的情况;试试Parallel.For