Вы пытаетесь применить слишком много вложенного параллелизма здесь.
Parallel.ForEach( <-- #1
contexts.AsParallel(), <-- #2
(context) => {
Parallel.ForEach( <- #3
Предполагая, что это работа с ЦП, вы действительно не хотите этого делать.Это потенциально может создать слишком много задач, которые необходимо будет сопоставить с потоками, что вызовет много непродуктивного переключения контекста.
Если предположить достаточное количество элементов во внешнем цикле с равными объемами, то этолучше просто сохранить параллелизм во внешнем цикле:
Parallel.ForEach(
contexts,
context => { ...
(И если количество элементов во внешнем цикле недостаточно, чтобы сохранить все ядра занятыми, или если дисперсия элементов во внутреннем IEnumerable
не является даже и приведет к тому, что задачи будут выполняться в разное время, а затем подумайте об использовании идеи @ TheGeneral об использовании contexts.SelectMany(c => c)
, то есть в форме outer.SelectMany(o => o.Inner)
, чтобы объединить вложенные коллекции в одну большую перед параллелизацией.
Если вы по-прежнему считаете, что параллелизм слишком высок для работы с процессором, вы можете сопоставить его с количеством реальных ядер на целевом компьютере, например, если у вас есть 8 доступных ядер:
Parallel.ForEach(
contexts,
new ParallelOptions { MaxDegreeOfParallelism = 8 },
context => { ...
Однако, если это будет использоваться для работы, связанной с вводом-выводом, то Parallel.For*
/ .AsParallel
являются неправильными инструментами - используйте асинхронный парадинструмент элизма, такой как Task.WhenAll
.