使用Parallel.ForEach <t>添加到新列表<t>

时间:2015-07-04 18:49:08

标签: c# multithreading parallel-processing task-parallel-library .net-4.5

使用并行化的最佳方法是什么,例如使用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;
}

2 个答案:

答案 0 :(得分:3)

最简单的解决方案是使用PLINQ及其扩展方法,例如ToListToDictionary。例如:

var result = days.AsParallel().SelectMany(d => FetchLegs(d))
                 .OrderBy(l => l.scheduledOut.Value).ToList();

答案 1 :(得分:1)

除了使用ConcurrentQueue之类的线程安全结构以及并行循环内的线程安全性之外,还可以将注释转移到答案中,或者您可以考虑自定义线程安全列表,请查看我的以下帖子 - Thread safe List。实际上,您可以考虑使用ReaderWriterSlim锁代替普通lock。 另一个要点是,您可以考虑使用ParallelOptions MaxDegreeOfParallelism,检查here,其值等于Environment.ProcessorCount,以便Parallel.ForEach分区工作正常,在开始时为集合中的每个数据点创建任务,它将基于系统中的逻辑核心数量来完成,从而有效地减少线程上下文切换并使应用程序更加高效