使用Parallel.ForEach<;T>;以添加到新列表<;T>
本文关键字:lt gt 列表 新列表 Parallel 使用 添加 ForEach | 更新日期: 2023-09-27 18:01:00
使用Parallel.ForEach等并行化的最佳方式是什么,这样我就可以快速迭代集合并将项目添加到新列表中,而不会违反线程安全性,但可以使用多个服务器核心和大量RAM的性能增益?
public List<Leg> FetchLegs(Trip trip)
{
var result = new List<Leg>();
try
{
// get days
var days = FetchDays(trip);
// add each day's legs to result
Parallel.ForEach<Day>(days, day =>
{
var legs = FetchLegs(day);
result.AddRange(legs);
});
// sort legs by scheduledOut
result.Sort((x, y) => x.scheduledOut.Value.CompareTo(y.scheduledOut.Value));
}
catch (Exception ex)
{
SiAuto.Main.LogException(ex);
System.Diagnostics.Debugger.Break();
}
return result;
}
最简单的解决方案是使用PLINQ
及其扩展方法,如ToList
、ToDictionary
。示例:
var result = days.AsParallel().SelectMany(d => FetchLegs(d))
.OrderBy(l => l.scheduledOut.Value).ToList();
将注释转移到答案,并提供更多建议,除了在Parallel循环中使用线程安全结构(如ConcurrentQueue(来实现线程安全之外,或者您可以考虑自定义线程安全列表,请查看我下面的帖子-线程安全列表。事实上,您可以考虑用ReaderWriterSlim
锁来代替普通的lock
。另一个重要的点是,你可以考虑使用ParallelOptions
MaxDegreeOfParallelism
,在这里检查值等于Environment.ProcessorCount
,这样Parallel.ForEach
partitioner就可以很好地工作,通过一开始不为集合中的每个数据点创建任务,它将根据系统中逻辑核心的数量来执行,从而有效地减少了线程上下文切换,并使应用程序更加高效。