C# 4.0 полное руководство - 2011
Шрифт:
В приведенном ниже примере программы демонстрируется порядок отмены параллельного запроса, сформированного в программе из предыдущего примера. В данной программе организуется отдельная задача, которая ожидает в течение 100 миллисекунд, а затем отменяет запрос. Отдельная задача требуется потому, что цикл foreach, в котором выполняется запрос, блокирует выполнение метода Main до завершения цикла.
using System.Linq; using System.Threading; using System.Threading.Tasks;
class PLINQCancelDemo {
static void Main {
CancellationTokenSource cancelTokSrc = new CancellationTokenSource; int[] data = new int[10000000];
//
//А теперь ввести в массив данных ряд отрицательных значений, 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 доступны и многие другие средства, помогающие подстраивать параллельные запросы под конкретную ситуацию. Так, при вызове метода WithDegreeOf Parallelism можно указать максимальное количество процессоров, выделяемых для обработки запроса, а при вызове метода As Sequential () — запросить последовательное выполнение части параллельного запроса. Если вызывающий поток, ожидающий результатов от цикла foreach, не требуется блокировать, то для этой цели можно воспользоваться методом ForAll . Все эти методы определены в классе ParallelEnumerable. А в тех случаях, когда PLINQ должен по умолчанию поддерживать последовательное выполнение, можно воспользоваться методом WithExecutionMode , передав ему в качестве параметра признак ParallelExecutionMode . ForceParallelism.
Вопросы эффективности PLINQ
Далеко не все запросы выполняются быстрее только потому, что они распараллелены. Как пояснялось ранее в отношении TPL, издержки, связанные с созданием параллельных потоков и управлением их исполнением, могут "перекрыть"
ГЛАВА 25 Коллекции, перечислители и итераторы
В этой главе речь пойдет об одной из самых важных составляющих среды .NET Framework: коллекциях. В C# коллекция представляет собой совокупность объектов. В среде .NET Framework имеется немало интерфейсов и классов, в которых определяются и реализуются различные типы коллекций. Коллекции упрощают решение многих задач программирования благодаря тому, что предлагают готовые решения для создания целого ряда типичных, но порой трудоемких для разработки структур данных. Например, в среду .NET Framework встроены коллекции, предназначенные для поддержки динамических массивов, связных списков, стеков, очередей и хеш-таблиц. Коллекции являются современным технологическим средством, заслуживающим пристального внимания всех, кто программирует на С#.
Первоначально существовали только классы необобщенных коллекций. Но с внедрением обобщений в версии C# 2.0 среда .NET Framework была дополнена многими новыми обобщенными классами и интерфейсами. Благодаря введению обобщенных коллекций общее количество классов и интерфейсов удвоилось. Вместе с библиотекой распараллеливания задач (TPL) в версии 4.0 среды .NET Framework появился ряд новых классов коллекций, предназначенных для применения в тех случаях, когда доступ к коллекции осуществляется из нескольких потоков. Нетрудно догадаться, что прикладной интерфейс Collections API составляет значительную часть среды .NET Framework.
Кроме того, в настоящей главе рассматриваются два средства, непосредственно связанные с коллекциями: перечислители и итераторы. И те и другие позволяют поочередно обращаться к содержимому класса коллекции в цикле foreach.
Краткий обзор коллекций
Главное преимущество коллекций заключается в том, что они стандартизируют обработку групп объектов в программе. Все коллекции разработаны на основе набора четко определенных интерфейсов. Некоторые встроенные реализации таких интерфейсов, в том числе ArrayList, Hashtable, Stack и Queue, могут применяться в исходном виде и без каких-либо изменений. Имеется также возможность реализовать собственную коллекцию, хотя потребность в этом возникает крайне редко.
В среде .NET Framework поддерживаются пять типов коллекций: необобщенные, специальные, с поразрядной организацией, обобщенные и параллельные. Необобщен-ные коллекции реализуют ряд основных структур данных, включая динамический массив, стек, очередь, а также словари, в которых можно хранить пары "ключ-значение". В отношении необобщенных коллекций важно иметь в виду следующее: они оперируют данными типа obj ect.
Таким образом, необобщенные коллекции могут служить для хранения данных любого типа, причем в одной коллекции допускается наличие разнотипных данных. Очевидно, что такие коллекции не типизированы, поскольку в них хранятся ссылки на данные типа object. Классы и интерфейсы необобщенных коллекций находятся в пространстве имен System.Collections.