5

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

4

5 回答 5

9

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

例子 :

Parallel.ForEach(
list.AsParallel().AsOrdered(), 
(listItems) => {<operations that you need to do>});
于 2018-04-26T19:42:20.393 回答
8

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

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

这种方法存在许多问题。

  1. 既不Parallel.ForParallel.ForEach不会保证您对内容的myData访问以任何特定顺序访问。
  2. 如果您是控制台上的方法或共享方法StringBuilder 来输出结果或构建完整的字符串,那么您可能会阻塞共享资源,从而有效地序列化并行循环的部分。

如果没有看到您的代码的具体示例,很难说更多。根据您所做的事情,您也许可以使用AsOrdered()PLINQ 中的订单保留来获得所需的位置。
请参阅此 MSDN 资源订购的 PLINQ ForAll

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

于 2011-03-30T12:32:59.300 回答
1

将其作为扩展方法

 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));

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

于 2020-03-14T10:46:56.477 回答
0

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

订购 PLINQ ForAll

于 2014-01-05T01:50:21.863 回答
-3

不,ForEach 仅用于顺序无关紧要的条件;试试Parallel.For

于 2010-11-09T16:43:42.423 回答