Полное руководство по языку программирования С# 14 и платформе .NET 10 / Parallel LINQ

Введение в Parallel LINQ. Метод AsParallel

Начальный ⏱ 3 мин чтения 👁 2 🕓 обновлено 11.08.2026

По умолчанию все элементы коллекции в LINQ обрабатываются последовательно, но начиная с .NET 4.0 в пространство имен System.Linq был добавлен класс ParallelEnumerable, который инкапсулирует функциональность PLINQ (Parallel LINQ) и позволяет выполнять обращения к коллекции в параллельном режиме.

При обработке коллекции PLINQ использует возможности всех процессоров в системе. Источник данных разделяется на сегменты, и каждый сегмент обрабатывается в отдельном потоке. Это позволяет произвести запрос на многоядерных машинах намного быстрее.

В то же время по умолчанию PLINQ выбирает последовательную обработку данных. Переход к параллельной обработке осуществляется в том случае, если это приведет к ускорению работы. Однако, как правило, при параллельных операциях возрастают дополнительные издержки. Поэтому если параллельная обработка потенциально требует больших затрат ресурсов, то PLINK в этом случае может выбрать последовательную обработку, если она не требует больших затрат ресурсов.

Поэтому смысл применения PLINQ имеется преимущественно на больших коллекциях или при сложных операциях, где действительно выгода от распараллеливания запросов может перекрыть возникающие при этом издержки.

Также следует учитывать, что при доступе к общему разделяемому состоянию в параллельных операциях будет неявно использоваться синхронизация, чтобы избежать взаимоблокировки доступа к этим общим ресурсам. Затраты на синхронизацию ведут к снижению производительности, поэтому желательно избегать или ограничивать применения в параллельных операциях разделяемых ресурсов.

Метод AsParallel

Метод AsParallel() позволяет распараллелить запрос к источнику данных. Он реализован как метод расширения LINQ у массивов и коллекций. При вызове данного метода источник данных разделяется на части (если это возможно) и над каждой частью отдельно производятся операции.

Рассмотрим простейший пример нахождения квадратов чисел:


int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, };
var squares = from n in numbers.AsParallel()
                 select Square(n);

foreach (var n in squares)
    Console.WriteLine(n);

int Square(int n) => n * n;

Фактически здесь обычный запрос LINQ, только к источнику данных применяется метод AsParallel.

Результат работы программы говорит о том, что данные выбирались для нахождения квадратов не последовательно. То есть произошло распараллеливание работы программы:

49
1
9
25
64
4
16
36

Аналогичная операция с помощью методов расширения:


var squares = numbers.AsParallel().Select(x => Square(x));

Метод ForAll

Выше рассмотренный код по вычислению квадрата числа можно еще больше оптимизировать с точки зрения параллелизации. В частности, для вывода результата параллельной операции используется цикл foreach. Но его использование приводит к увеличению издержек - необходимо склеить полученные в разных потоках данные в один набор и затем их перебрать в цикле. Более оптимально в данном случае было бы использование метода ForAll(), который выводит данные в том же потоке, в котором они обрабатываются:


int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, };

// с помощью операторов LINQ
(from n in numbers.AsParallel() select Square(n)).ForAll(Console.WriteLine);

// с помощью методов расширения LINQ
numbers.AsParallel().Select(n => Square(n)).ForAll(Console.WriteLine);

int Square(int n) => n * n;

Метод ForAll() в качестве параметра принимает делегат Action, который указывает на выполняемое действие.

Проверь себя

📋 Тест по теме «Введение в Parallel LINQ. Метод AsParallel» Тест по теме

Практические задания

Лёгкое Ручная проверка Заполните пропуск в коде (1)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

int[] _____ = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, };
var squares = from n in numbers.AsParallel()
                 select Square(n);

foreach (var n in squares)
    Console.WriteLine(n);

int Square(int n) => n * n;
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (2)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

var squares = _____.AsParallel().Select(x => Square(x));
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (3)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

int[] numbers = new int[] { _____, 2, 3, 4, 5, 6, 7, 8, };

// с помощью операторов LINQ
(from n in numbers.AsParallel() select Square(n)).ForAll(Console.WriteLine);

// с помощью методов расширения LINQ
numbers.AsParallel().Select(n => Square(n)).ForAll(Console.WriteLine);

int Square(int n) => n * n;
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (4)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

int[] numbers = new int[] { 1, 2, 3, 4, _____, 6, 7, 8, };
var squares = from n in numbers.AsParallel()
                 select Square(n);

foreach (var n in squares)
    Console.WriteLine(n);

int Square(int n) => n * n;
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (5)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

var squares = numbers._____().Select(x => Square(x));
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (1)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, };
var _____ = from n in numbers.AsParallel()
                 select Square(n);

foreach (var n in squares)
    _____.WriteLine(n);

int Square(int n) => n * n;
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (2)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

var _____ = numbers._____().Select(x => Square(x));
Войдите, чтобы отправить решение
Среднее Ручная проверка Расставьте строки кода в правильном порядке
+20 XP

Строки кода из примера этого урока перемешаны. Впишите их в правильном порядке, каждую строку — с новой строки.

                 select Square(n);
var squares = from n in numbers.AsParallel()
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, };
    Console.WriteLine(n);
int Square(int n) => n * n;
foreach (var n in squares)
Войдите, чтобы отправить решение
Сложное Ручная проверка Объясните и модифицируйте пример из урока «Введение в Parallel LINQ. Метод AsParallel»
+30 XP

Опишите своими словами, что делает приведённый пример кода из урока «Введение в Parallel LINQ. Метод AsParallel», и предложите одно осмысленное изменение (например, другое входное значение или дополнительное условие). Приведите итоговый код.

int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, };
var squares = from n in numbers.AsParallel()
                 select Square(n);

foreach (var n in squares)
    Console.WriteLine(n);

int Square(int n) => n * n;
Войдите, чтобы отправить решение
Сложное Ручная проверка Найдите потенциальную проблему в коде урока «Введение в Parallel LINQ. Метод AsParallel»
+30 XP

Изучите приведённый фрагмент кода и опишите, при каких входных данных или условиях он может сработать не так, как ожидается (граничный случай, отсутствие проверки и т.п.). Предложите исправленный вариант.

var squares = numbers.AsParallel().Select(x => Square(x));
Войдите, чтобы отправить решение
Мини-проект Ручная проверка Мини-проект по теме «Введение в Parallel LINQ. Метод AsParallel»
+50 XP

Соберите небольшую программу, которая последовательно демонстрирует ключевые идеи урока. Программа должна быть рабочей и содержать минимум два самостоятельно написанных фрагмента, а не просто копию примера из урока.

Войдите, чтобы отправить решение
Домашнее задание Ручная проверка Домашнее задание по теме «Введение в Parallel LINQ. Метод AsParallel»
+25 XP

Напишите собственную небольшую программу, применяющую материал темы «Введение в Parallel LINQ. Метод AsParallel». Используйте не менее одной конструкции, показанной в примерах урока. Прикрепите код решения и краткое описание того, что он делает.

Войдите, чтобы отправить решение

Обсуждение (0)

Войдите, чтобы оставить комментарий.