使用Parallel.ForEach()
时有办法保证订单吗?我正在循环的集合需要保持它的顺序,但我正在寻找一些性能改进。
答案 0 :(得分:6)
所以你有一个看起来像这样的陈述? (根据您的上述评论)。
Parallel.Foreach(myData, ..., (d) =>
{
StringBuilder sb = new StringBuilder();
sb.Append(d);
// WriteLine sb?
});
这种方法存在许多问题。
Parallel.For
或Parallel.ForEach
都不会保证您以任何特定顺序访问myData
的内容。 StringBuilder
要么输出结果,要么建立一个完整的字符串
可能是在共享资源上阻塞,有效地序列化
并行循环的一部分。如果没有看到代码的具体示例,很难说更多。根据您的工作情况,您可以使用PLINQ中的订单保存AsOrdered()
来获取您想要的位置。
请参阅this MSDN Resource和
Ordered 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
)作为以下问题答案的一部分:
答案 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