public static ParallelQuery AsOrdered(this ParallelQuery source)
public static ParallelQuery
AsOrdered
где TSource обозначает тип элементов в источнике данных AsOrdered()
можно вызывать только для объекта типа ParallelQuery
, поскольку он является методом расширения класса ParallelQuery
.
Для того чтобы посмотреть, к какому результату может привести применение метода AsOrdered()
, подставьте его вызов в приведенный ниже запрос из предыдущего примера программы.
// Использовать метод AsOrdered() для сохранения порядка
// в результирующей последовательности.
var negatives = from val in data.AsParallel().AsOrdered() where val < 0 select val;
После выполнения программы порядок следования элементов в результирующей последовательности будет отражать порядок их расположения в исходной последовательности.
Параллельный запрос отменяется таким же образом, как и задача. И в том и в другом случае отмена опирается на структуру CancellationToken
, получаемую из класса CancellationTokenSource
. Получаемый в итоге признак отмены передается запросу с помощью метода WithCancellation()
. Отмена параллельного запроса производится методом Cancel()
, который вызывается для источника признаков отмены. Главное отличие отмены параллельного запроса от отмены задачи состоит в следующем: когда параллельный запрос отменяется, он генерирует исключение OperationCanceledException
, а не AggregateException
. Но в тех случаях, когда запрос способен сгенерировать несколько исключений, исключение OperationCanceledException
может быть объединено в совокупное исключение AggregateException
. Поэтому отслеживать лучше оба вида исключений.
Ниже приведена форма объявления метода WithCancellation()
:
public static ParallelQuery
this ParallelQuery
CancellationToken cancellationToken)
где
В приведенном ниже примере программы демонстрируется порядок отмены параллельного запроса, сформированного в программе из предыдущего примера. В данной программе организуется отдельная задача, которая ожидает в течение 100 миллисекунд, а затем отменяет запрос. Отдельная задача требуется потому, что цикл foreach
, в котором выполняется запрос, блокирует выполнение метода Main()
до завершения цикла.
// Отменить паралельный запрос
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class PLINQCancelDemo {
static void Main() {
CancellationTokenSource cancelTokSrc = new CancellationTokenSource();
int[] data = new int[10000000];
// Инициализировать массив данных положительными значениями,
for (int i=0; i < data.Length; i++) data[i] = i;
//А теперь ввести в массив данных ряд отрицательных значений,
data[1000] = -1;
data [14000] = -2;
data[15000] = -3;
data[676000] = -4;
data[8024540] = -5;
data [9908000] = -6;
// Использовать запрос PLINQ для поиска отрицательных значений,
var negatives = from val in
data.AsParallel(). WithCancellation(cancelTokSrc.Token)
where val < 0
select val;
// Создать задачу для отмены запроса по истечении 100 миллисекунд.
Task cancelTsk = Task.Factory.StartNew(() => {
Thread.Sleep(100);
cancelTokSrc.Cancel();
});
try {
foreach(var v in negatives)
Console.Write(v + " ");
} catch(OperationCanceledException exc) {
Console.WriteLine(exc.Message);
} catch(AggregateException exc) {