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

Вы хотите перетасовать каждую партию из трех элементов? – 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. Я собирался предложить что-то подобное на самом деле - имейте в виду, что документация Microsoft для Parallel.ForEach явно заявляет, что они не гарантируют определенный порядок выполнения, поэтому вам почти нужно сделать что-то подобное , – 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.MaxDegreeOfParallelism в 1, вы получите желаемый заказать параллельный исполнение, кусок куском.

+0

Спасибо, я попробую завтра. –

Смежные вопросы