Параллельная обработка, внутренний цикл, можем ли мы получить доступ к степени параллелизма?

В следующем цикле я хочу добавить логику, чтобы сказать, что если процессор 1 сделает это, если процессор 2 сделает то и т. д. Я пробовал различные свойства, такие как...

Console.WriteLine("Domain ID = " + Thread.GetDomainID().ToString());
Console.WriteLine("Thread ID = " + Thread.CurrentThread.ManagedThreadId.ToString());

... но я вижу, что идентификатор потока увеличивается и увеличивается, поэтому это поток, в котором много потоков к процессору. Итак, как получить 1-4 внутри цикла? DomainID я просто получаю то же значение

Parallel.ForEach(list.OrderBy(n => n.ScheduledBillingId),
    new ParallelOptions { MaxDegreeOfParallelism = 4  }, (item) => { });

Моя проблема в том, что я хочу, чтобы это могло разделить записи в списке на 4 группы и обработать 1 с первыми 25% и так далее.


person John    schedule 10.04.2017    source источник
comment
Обычно я бы рекомендовал не использовать parallel.foreach внутри кода asp.net - asp.net уже пытается использовать пул потоков для одновременной обработки нескольких запросов.   -  person Damien_The_Unbeliever    schedule 10.04.2017
comment
Если вы хотите делать что-то другое в каждом потоке, то Parallel.ForEach может оказаться неподходящим инструментом. Можете ли вы уточнить, что именно вам нужно и почему? Например, не могли бы вы показать, какой код вы бы написали, если бы у вас была искомая информация?   -  person Kevin Gosse    schedule 10.04.2017
comment
foreach (Элемент ScheduledBilling в list.OrderBy(n => n.ScheduledBillingId)) { } Я просто хочу, чтобы это веб-задание обрабатывало разные пакеты этого списка параллельно, чтобы ускорить все это. С конца до конца это медленно   -  person John    schedule 10.04.2017
comment
Но меня беспокоит то, что он пытается запустить один и тот же элемент одновременно, так как я получаю ошибки базы данных. Как если бы процесс 1 и процесс 2 и т. д. все пытались выполнить первый элемент. Новичок в параллельной обработке и не уверен, что мне нужно делать больше   -  person John    schedule 10.04.2017
comment
Разметка не связана с DOP. Косвенно Parallel.For/Foreach использует DOP для разделения. Почему тебя это волнует? Каждая задача выполняет ту же работу, что и любая другая. Вам совершенно все равно, на какой задаче обрабатывается запись   -  person Panagiotis Kanavos    schedule 10.04.2017
comment
С другой стороны, распараллеливание плохого запроса сделает его только хуже, намного хуже. Параллельные операции не ускорят неправильные запросы и определенно не будут выполняться быстрее, чем операция SqlBulkCopy. Если у вас возникли проблемы с кодом вашей базы данных, опубликуйте код базы данных. Вы не получите никаких улучшений, если попытаетесь записать на один и тот же диск из нескольких потоков. Объединяйте все новые строки вместе и отправляйте их все одним вызовом   -  person Panagiotis Kanavos    schedule 10.04.2017
comment
Есть ли способ узнать процесс внутри цикла, т.е. 1-4. Это все, что мне нужно. Запрос эффективен, а не проблема. Внутренний вызов связан с тем, что он генерирует PDF-файл и выполняет большую проверку. В дальнейшем это будет улучшаться/настраиваться. Но мы хотим использовать аппаратное обеспечение, и нам нужен быстрый способ запустить более 1 поезда, используя 4   -  person John    schedule 10.04.2017
comment
Я никогда раньше не упоминал, что это веб-задание, работающее в единственном числе, а не часть решения веб-сайта asp.net. Итак, идея в том, что коду требуется, скажем, 1 час, чтобы выполнить 100 задач, поэтому я хочу, чтобы 4 задачи выполнялись быстрее. Проблема в том, как сказать четырем процессам не наступать друг другу на пятки, так как это база данных. Я получаю сообщение об ошибке "Элемент с таким же ключом уже добавлен"   -  person John    schedule 10.04.2017


Ответы (1)


Для работы и Parallel.ForEach вы можете использовать разделитель списка, как это:

// Partition the entire source array.
var rangePartitioner = Partitioner.Create(0, list.Count);

После этого вы просто предоставляете этот разделитель для своего цикла:

Parallel.ForEach(rangePartitioner, (range, loopState) =>
{
    // Loop over each range element without a delegate invocation.
    for (var i = range.Item1; i < range.Item2; ++i)
    {
        var taskToRun = list[i];
    }
});

Поскольку вы хотите разделить свои задачи на 4 группы, вам просто нужна правильная перегрузка< /а>:

var rangePartitioner = Partitioner.Create(0, source.Length, source.Length / 4);
person VMAtm    schedule 13.04.2017