Метод AsOrdered


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

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

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

int Square(int n) => n * n;
В данном случае программа вычисляет квадраты чисел, которые больше 0. Однако в результате работы программы мы можем получить неупорядоченный вывод:

1
16
49
4
25
64
9
36
То есть данные склеиваются в общий набор неупорядоченно.

Если в запросе применяются операторы или методы сортировки в запросе, данные автоматически упорядочиваются:

var squares = from n in numbers.AsParallel()
where n > 0
orderby n // сортировка
select Square(n);
Однако не всегда оператор orderby или метод OrderBy используются в запросах. Более того они упорядочивают результирующую выборку в соответствии с результатами, а не в соответствии с исходной последовательностью. В этих случаях мы может применять метод AsOrdered():

var squares = from n in numbers.AsParallel().AsOrdered()
where n > 0
select Square(n);
В этом случае результат уже будет упорядоченным в соответствии с тем, как элементы располагаются в исходной последовательности:

1
4
9
16
25
36
49
64
В то же время надо понимать, что упорядочивание в параллельной операции приводит к увеличению издержек, поэтому подобный запрос будет выполняться медленнее, чем неупорядоченный. И если задача не требует возвращение упорядоченного набора, то лучше не применять метод AsOrdered.

Кроме того, если в программе предстоят какие-нибудь манипуляции с полученным набором, однако упорядочивание больше не требуется, мы можем применить метод AsUnordered():

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

// выбираем числа больще 4 без упорядочивания результата
var query = from n in squares.AsUnordered()
where n > 4
select n;

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

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