在Parallel.Foreach中分块IEnumerable

bjo*_*ern 21 .net c# parallel-processing multithreading

有没有人知道让Parallel.Foreach循环使用块分区的方法,我认为默认情况下是范围分区.使用数组时似乎很简单,因为您只需创建自定义分区程序并将负载均衡设置为true即可.

由于IEnumerable中的元素数量直到运行时才知道,因此我似乎无法找到使块分区工作的好方法.

任何帮助,将不胜感激.

谢谢!

我试图在每个对象上执行的任务执行的时间明显不同.最后,我通常会等待最后一个线程完成其工作的时间.我想要实现的是在整个过程中使用并行循环请求块而不是为每个线程预分配项.

Sco*_*ain 22

如果您的IEnumerable真的是一个有索引器的东西(即你可以做obj[1]一个项目),你可以做以下事情

    var rangePartitioner = Partitioner.Create(0, source.Length);
    Parallel.ForEach(rangePartitioner, (range, loopState) =>
    {
        // Loop over each range element without a delegate invocation. 
        for (int i = range.Item1; i < range.Item2; i++)
        {
            var item = source[i]
            //Do work on item
        }
    });
Run Code Online (Sandbox Code Playgroud)

但是,如果它不能这样做,您必须通过创建派生自的新类来编写自定义分区程序System.Collections.Concurrent.Partitioner<TSource>.该主题过于宽泛,无法在SO答案中涵盖,但您可以在MSDN上查看本指南以帮助您入门.

更新:从.NET 4.5开始,他们添加了一个Partitioner.Create不缓冲数据的重载,它与制作一个范围最大为1的自定义分区具有相同的效果.这样你就不会得到一个有一堆的单个线程如果一连串的慢速项目运气不好,就排队等候工作.

var partitoner = Partitioner.Create(source, EnumerablePartitionerOptions.NoBuffering);
Parallel.ForEach(partitoner, item =>
{
    //Do work
}
Run Code Online (Sandbox Code Playgroud)