块分区在Parallel.Foreach中可枚举

本文关键字:枚举 Foreach Parallel 分区 | 更新日期: 2023-09-27 18:12:26

有没有人知道如何获得平行?Foreach循环使用块分区,而不是默认的范围分区。在处理数组时,这似乎很简单,因为您只需创建一个自定义分区并将负载平衡设置为true。

由于IEnumerable中的元素数量直到运行时才知道,我似乎找不到一个好方法来获得块分区的工作。

如有任何帮助,不胜感激。

谢谢!

我试图在每个对象上执行的任务需要明显不同的时间来执行。最后,我通常要等上几个小时,等待最后一个线程完成它的工作。我想要实现的是在并行循环请求块的过程中,而不是预先分配项目到每个线程。

块分区在Parallel.Foreach中可枚举

如果你的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
        }
    });

但是,如果它不能这样做,您必须通过创建从System.Collections.Concurrent.Partitioner<TSource>派生的新类来编写自定义分区器。这个主题太宽泛了,不能在SO的答案中涵盖,但是你可以看看MSDN上的这个指南来开始。

UPDATE:在。net 4.5中,他们添加了一个Partitioner.Create过载,它不缓冲数据,它具有与创建一个范围最大大小为1的自定义分区相同的效果。有了这个,你就不会得到一个线程,有一堆排队的工作,如果它不幸与一堆慢的项目在一行。

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