День 1102. #ЗаметкиНаПолях #AsyncTips
Параллельный Вызов
Задача: имеется набор методов, которые должны вызываться параллельно. Эти методы (в основном) независимы друг от друга.
Решение
Класс Parallel содержит простой метод Invoke, спроектированный для таких сценариев. В следующем примере массив разбивается надвое, и две половины обрабатываются независимо:
void Process(double[] arr)
{
Parallel.Invoke(
() => ProcessPartial(arr, 0, arr.Length/2),
() => ProcessPartial(arr, arr.Length/2, arr.Length)
);
}
void ProcessPartial(double[] array, int begin, int end)
{
// Обработка, интенсивно использующая процессор...
}
Методу Parallel.Invoke также можно передать массив делегатов, если количество вызовов неизвестно до момента выполнения:
void DoActions(Action action)
{
Action[] actions = Enumerable.Repeat(action, 20).ToArray();
Parallel.Invoke(actions);
}
Parallel.Invoke поддерживает отмену, как и другие методы класса Parallel:
void DoActions(Action action, CancellationToken token)
{
Action[] actions = Enumerable.Repeat(action, 20).ToArray();
Parallel.Invoke(
new ParallelOptions { CancellationToken = token },
actions);
}
Метод Parallel.Invoke — отличное решение для простого параллельного вызова. Отмечу, что он уже не так хорошо подходит для ситуаций, в которых требуется активизировать действие для каждого элемента входных данных (для этого лучше использовать Parallel.ForEach), или если каждое действие производит некоторый вывод (вместо этого следует использовать Parallel LINQ).
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 4.