4

我有一个像[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]这样的有序列表。我将它传递给Parallel.ForEach声明。我可以以某种方式实现以下执行存储桶的顺序:处理前3个项目[1, 2, 3],其中存储桶本身的排序不是必需的,例如可以是[2, 1, 3]。然后处理下3项[4, 5, 6]等?有序并行执行

+0

你是说你想洗牌每批3个元素? – tinstaafl

+0

不,我说的是批量订购:前3个,然后是下3个,但里面的订单可能是随机的 - 不是强制性的在水桶内订购 –

回答

5

我不确定您是否可以直接进行此操作。但我建议您将输入列表分成较小的列表,然后您可以使用Parallel.Foreach处理每个子列表。

List<int> fruits = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
List<List<int>> ls = new List<List<int>>(); 
for (int i = 0; i < fruits.Count; i += 3) 
{ 
    ls.Add(fruits.GetRange(i, Math.Min(3, fruits.Count - i))); 
} 
foreach (List<int> group in ls) 
{ 
    Parallel.ForEach(group, fruit => 
    { 
    }); 
} 

3是小列表的长度。

+0

你确定这会起作用吗?让我试试 –

+1

@GiorgiNakeurl我将会建议一些类似的东西 - 请记住,Parallel.ForEach的Microsoft文档明确声明它们不保证特定的执行顺序,所以你几乎不得不做这样的事情。 – EJoshuaS

+0

嗯,这个工程。我想试试这个,但我不相信它会工作:) –

2

即使接受的答案完全符合要求,它也会有一些开销。首先,当我们谈论TPL时,数据阵列的体积可能很大,所以简单地创建这么多的阵列非常耗费内存。
此外,@viveknuna建议的解决方案不保证块的顺序。如果它是好的,你应该使用来自@DmitryBychenko答案的小更新:

const int chunkSize = 3; 
var array = Enumerable.Range(1, 9).ToArray(); 
// get the chunks for indexes for array sized in group of 3 
var partitioner = Partitioner.Create(0, array.Length, chunkSize); 

// use all the system resources 
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; 

// use the partitioner for a chunks, so outer parallel foreach 
// will start a task for all the chunks, [1, 2, 3], [4, 5, 6], [7, 8, 9] 
Parallel.ForEach(partitioner, parallelOptions, part => 
    { 
     // inner foreach will handle part of the chunk in parallel 
     Parallel.ForEach(array.Skip(part.Item1).Take(chunkSize), parallelOptions, value => 
      { 
       // handle the array value in parallel 
      }); 
    }); 

在给定的代码,如果你设置了ParallelOptions.MaxDegreeOfParallelism1,你会得到期望的有序并行执行,块大块。

+0

谢谢,明天我会试一试。 –