Ниже приведена форма объявления метода WithCancellation():
public static ParallelQuery WithCancellation (
this ParallelQuery source,
CancellationToken cancellationToken)
где source обозначает вызывающий запрос, a 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) {
Console.WriteLine (exc);
} finally {
cancelTsk.Wait();
cancelTokSrc.Dispose();
cancelTsk.Dispose();
}
Console.WriteLine();
}
}
Ниже приведен результат выполнения этой программы. Если запрос отменяется до его завершения, то на экран выводится только сообщение об исключительной ситуации.
Запрос отменен с помощью маркера, переданного в метод WithCancellation.
Другие средства PLINQ
Как упоминалось ранее, PLINQ представляет собой довольно крупную подсистему. Это объясняется отчасти той гибкостью, которой обладает PLINQ. В PLINQ доступны и многие другие средства, помогающие подстраивать параллельные запросы под конкретную ситуацию. Так, при вызове метода WithDegreeOfParallelism()можно указать максимальное количество процессоров, выделяемых для обработки запроса, а при вызове метода AsSequential()— запросить последовательное выполнение части параллельного запроса. Если вызывающий поток, ожидающий результатов от цикла foreach, не требуется блокировать, то для этой цели можно воспользоваться методом ForAll(). Все эти методы определены в классе ParallelEnumerable. А в тех случаях, когда PLINQ должен по умолчанию поддерживать последовательное выполнение, можно воспользоваться методом WithExecutionMode(), передав ему в качестве параметра признак ParallelExecutionMode.ForceParallelism.
Вопросы эффективности PLINQ
Далеко не все запросы выполняются быстрее только потому, что они распараллелены. Как пояснялось ранее в отношении TPL, издержки, связанные с созданием параллельных потоков и управлением их исполнением, могут "перекрыть" все преимущества, которые дает распараллеливание. Вообще говоря, если источник данных оказывается довольно мелким, а требующаяся обработка данных — очень короткой, то внедрение параллелизма может и не привести к ускорению обработки запроса. Поэтому за рекомендациями по данному вопросу следует обращаться к информации корпорации Microsoft.
ГЛАВА 25 Коллекции, перечислители и итераторы
В этой главе речь пойдет об одной из самых важных составляющих среды .NET Framework: коллекциях. В C# коллекция представляет собой совокупность объектов. В среде .NET Framework имеется немало интерфейсов и классов, в которых определяются и реализуются различные типы коллекций. Коллекции упрощают решение многих задач программирования благодаря тому, что предлагают готовые решения для создания целого ряда типичных, но порой трудоемких для разработки структур данных. Например, в среду .NET Framework встроены коллекции, предназначенные для поддержки динамических массивов, связных списков, стеков, очередей и хеш-таблиц. Коллекции являются современным технологическим средством, заслуживающим пристального внимания всех, кто программирует на С#.
Читать дальше