При выполнении параллельного запроса порядок данных в результирующей выборки может быть не предсказуем. Например:
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;