TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.77K subscribers
Post #1311 1.39K
День 1065. #ЗаметкиНаПолях #AsyncTips
Параллельная обработка данных
Задача:
Имеется коллекция данных. Требуется выполнить одну и ту же операцию с каждым элементом. Эта операция является ограниченной по вычислениям и может занять некоторое время.

Решение
Тип Parallel содержит метод ForEach, разработанный специально для этой задачи. Следующий пример получает коллекцию матриц и поворачивает эти матрицы:
void Rotate(IEnumerable<Matrix> matrices, float degrees)
{
Parallel.ForEach(matrices, m => m.Rotate(degrees));
}

Возможны ситуации, в которых преждевременно требуется прервать цикл (например, при обнаружении недействительного значения). Следующий пример обращает каждую матрицу, но при обнаружении недействительной матрицы цикл прерывается:
void Invert(IEnumerable<Matrix> matrices)
{
Parallel.ForEach(matrices, (m, state) =>
{
if (!m.IsInvertible)
state.Stop();
else
m.Invert();
});
}

Этот код использует ParallelLoopState.Stop для остановки цикла и предотвращения любых дальнейших вызовов тела цикла. Учтите, что цикл является параллельным, поэтому могут уже выполниться другие вызовы тела цикла, включая вызовы для элементов, следующих после текущего. В приведённом примере кода если третья матрица не является обратимой, то цикл прерывается и новые матрицы обрабатываться не будут, но может оказаться, что уже обрабатываются другие матрицы (например, четвертая и пятая).

Более распространённая ситуация встречается тогда, когда требуется отменить параллельный цикл. Это не то же, что остановка: цикл останавливается изнутри и отменяется за своими пределами. Например, кнопка отмены может отменить CancellationTokenSource, отменяя параллельный цикл, как в следующем примере:
void Rotate (IEnumerable<Matrix> matrices, 
float degrees, CancellationToken t)
{
Parallel.ForEach(matrices,
new ParallelOptions { CancellationToken = t },
m => m.Rotate(degrees));
}

Следует иметь в виду, что каждая параллельная задача может выполняться в отдельном потоке, поэтому любое совместное состояние должно быть защищено. Следующий пример обращает каждую матрицу и подсчитывает количество матриц, которые обратить не удалось:
// Примечание: это не самая эффективная реализация.
// Это лишь пример использования блокировки
// для защиты совместного состояния.
int Invert(IEnumerable<Matrix> matrices)
{
object mutex = new object();
int nonInvertible = 0;
Parallel.ForEach(matrices, m => {
if (matrix.IsInvertible)
m.Invert();
else
{
lock (mutex)
{
++nonInvertible;
}
}
});
return nonInvertible;
}

Метод Parallel.ForEach предоставляет возможность параллельной обработки последовательности значений. Аналогичное решение Parallel LINQ (PLINQ) предоставляет практически те же возможности в LINQ-подобном синтаксисе. Одно из различий между Parallel и PLINQ заключается в том, что PLINQ предполагает, что может использовать все ядра на компьютере, тогда как Parallel может динамически реагировать на изменения условий процессора.

Parallel.ForEach реализует параллельный цикл foreach. Если вам потребуется выполнить параллельный цикл for, то класс Parallel также поддерживает метод Parallel.For. Метод Parallel.For особенно полезен при работе с несколькими массивами данных, которые получают один индекс.

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 4.
  • 👍 3
More from @netdeveloperdiary
  1. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  2. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
  3. Oct 7, 2026День 2807. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Окончание Нач…
  4. Oct 6, 2026🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК Приглашаем на открытое собес…
  5. Oct 6, 2026День 2806. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Начало Больши…
  6. Oct 5, 2026День 2805. #ЧтоНовенького #NET11 Аргументы в Выражениях Коллекций в C#15 В C#15 реализован…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →