Г. Шилдт - С#4.0 Полное руководство (1160795), страница 185
Текст из файла (страница 185)
Имеются как обобщенный, так и необобщенный варианты данного класса. Мы не будем обращаться к классу Рага11е11]негу непосредственно, а воспользуемся несколькими методами класса Рага11е1ЕпивегаЬ1е. Самый главный из них, метод Азрага11е1 (), описывается в следующем разделе. Распарамеливание запроса методом АвРага11е1 () Едва ли не самым удобным средством РЬ1)Х[ ) является возможность просто создавать параллельный запрос.
Нужно лишь вызвать метод Азрага11е1 () для источника данных. Метод йзрага11е1 () определен в классе Рага11е1ЕпивегаЬ1е и возвращает источник данных, инкапсулированный в экземпляре объекта типа Рага11е13иегу. Это дает возможность поддерживать методы расширения параллельных запросов. После вызова данного метода запрос разделяет источник данных на части и оперирует с каждой из них таким образом, чтобы извлечь максимальную выгоду из распараллеливания. (Если распараллеливание оказывается невозможным или неприемлемым, то запрос, как обычно, выполняется последовательно.) Таким образом, добавления в исходный код единственного вызова метода АзРага11е1 () оказываетгя достаточно для того, чтобы превратить последовательный запрос [.1ХЯ в параллельный запрос Ь1]>)( с Для простых запросов это единственное необходимое условие.
Существуют как обобщенные, так и необобщенные формы метода Аз Рага11е1 () . Ниже приведена простейшая обобщенная его форма: риЬ11с зСасгс Рага11е10иегу йзРага11е1 (Сйьз 1Епвьегаше зоигсе) риь1>с зсас1с Рага11е10иегу<тзоигсе> йаРага11е1<тзоигсе> (Сига гепивегаЬ1е<тзоигсе> зоигсе] где тэоигсе обозначает тип элементов в последовательном источнике данных зоигсе. Ниже приведен пример, демонстрирующий простой запрос Г1Д)>[( Ь О Простой запрос РЫН0. изгпэ 5узСевГ изгпс зузгев.ьгпьи с1азз РШН00ево зсасгс чогб Ма1п() ( 1пс[) баса = лен гпС[10000000]г Инициализировать массив данных положительными значениями. йог(гпс 1=0; 1 < баса.Ьепэсп! 1++) баСа[г) й теперь ввести а массив данных ряд отрицательных значений.- бага[1000] = -1; баса[14000) = -21 баса[15000) = -31 баса[676000) = -41 Глава 24.
Многопоточное программирование. Часть вторая: библиотека тРЕ 919 баСа[8024540) = -5; бага[9908000) = -б; О использовать запрос Ршно ллн поиска отрицательных значений. чаг печагсчея = Гсов ча1 гп бага.АяРага11е1() ипате ча1 < 0 яе1есг ча1; Гогеасп(чаг ч 1п печаг1чея) Сопяо1е.иг1ге(ч + " "); Сопяо1е.нгггесгпе(); ) ) Эта программа начинается с создания крупного массива бага, инициализируемого целыми положительными значениями. Затем в него вводится ряд отрицательных значений. А далее формируется запрос на возврат последовательности отрицательных значений. Ниже приведен этот запрос.
чаг педаСгчея = Ггов ча1 гп баоа.йярага11е1() инесе ча1 < 0 яе1есг ча1; В этом запросе метод Аярага11е1 () вызывается для источника данных, в качестве которого служит массив баса. Благодаря этому разрешаетсл параллельное выполнение операций над массивом баса, а именно: поиск отрицательных значений параллельно в нескольких потоках.
По мере обнаружения отрицательных значений они добавляются в последовательность вывода. Это означает, что порядок формирования последовательности вывода может и не отражать порядок расположения отрицательных значений в массиве баса. В качестве примера ниже приведен результат выполнения приведенного выше кода в двухъядерной системе. -5 -б -1 -2 -3 -4 Как видите, в том потоке, где поиск выполнялся в верхней части массива, отрицательные значения -5 и -6 были обнаружены раньше, чем значение -1 в том потоке, где поиск происходил в нижней части массива. Следует, однако, иметь в виду, что из-за отличий в степени загрузки задачами, количества доступных процессоров и прочих факторов системного характера могут быль получены разные результаты. А самое главное, что результирующая последовательность совсем не обязательно будет отражать порядок формирования исходной последовательности.
Применение метода АеОгйехей () Как отмечалось в предыдущем разделе, по умолчанию порядок формирования результирующей последовательности в параллельном запросе совсем не обязательно должен отражать порядок формирования исходной последовательности. Более того, результирующую последовательность следует рассматривать как практически неупорядоченную. Если же результат должен отражать порядок организации источника данных, то его нужно запросить специально с помощью метода Аяо лбе ге б ( ), определенного в классе Рага11е1кпцвега)о1е. Ниже приведены обобщенная и необобщенная формы этого метода: 920 часть Н.
Бибяиатека С№ риЫТс ягаС1а Рага11егоиегу йяогдегед(сшя Рага11е1Оиегу яоигсе) риЫтс ягаС1с Рага11е1Оиегу<ТЯоигае> Аяогдегед<ТЯоигсе>(СЫя Рага11е1Оиегу<ТЯоигсе> яаигсе) где ТЯоигсе обозначает тип элементов в источнике данных яоигсе. Метод АЯОгдегед () можно вызывать только для объекта типа Рага11е1Оиегу, поскольку он является методом расширения класса Рага11е1Оиегу. Для того чтобы посмотреть, к какому результату может привести применение метода АЯОгде сед (), подставьте его вызов в приведенный ниже запрос из предыдущего примера программы. // Использовать метод Аяогдегед() для сохранения порядка // в результируюшей последовательности. иаг пеэаС1иея = ггош уа1 гп дага.й*рага11е1().йяогдегед() маете уа1 < О яе1есс уа1г После выполнения программы порядок следования элементов в результирующей последовательности будет отражать порядок их расположения в исходной последовательности. Отмена параллельного запроса Параллельный запрос отменяется таким же образом, как и задача.
И в том и в другом случае отмена опирается на структуру Сапае11аСТопТО)сеп, получаемую из класса Сапсе11аСТопТойепэаигсе. Получаемый в итоге признак отмены передается запросу с помощью метода Н1С)ССапае11аС1оп () . Отмена параллельного запроса производится методом Сап се 1 ( ), который вызывается для источника признаков отмены.
Главное отличие отмены параллельного запроса от отмены задачи состоит в следующем: когда параллельный запрос отменяется, он генерирует исключение Орегас№опСапсе1ес)Ехсерсгоп, а не А00гедасеЕхаерС1оп. Но в тех случаях, когда запрос способен сгенерировать несколько исключений, исключение Оре гас гапСапсе1едЕхсерс Топ может быть объединено в совокупное исключение АдчгеаасеЕхсерСТоп. Поэтому отслеживать лучше оба вида исключений. Ниже приведена форма объявления метода Н1С)ССапсе11аС1оп (); риЫгс яСаС1с Рага11е1оиегу<ТЯаигсе> Х1СПСапсе11аггоп<ТЯоигсе> СЫя Рага11е1Оиегу<ТЯоигсе> яоигсе, Сапсе11агтопТохеп сапсе11аСдопТогеп) где яаигсе обозначает вызывающий запрос, а сапсе11а С1оптахеп — признак отмены.
Этот метод возвращает запрос, поддерживающий указанный признак отмены. В приведенном ниже примере программы демонстрируется порядок отмены параллельного запроса, сформированного в программе из предыдущего примера. В данной программе организуется отдельная задача, которая ожидает в течение 100 миллисекунд, а затем отменяет запрос. Отдельная задача требуется потому, что цикл Тогеаа)г, в котором выполняется запрос, блокирует выполнение метода Натп () до завершения цикла.
Отменить параллельный запрос. ия1пч Яуягешг Глава 24. Многопоточное программирование. Часть вторая: библиотека ТРЕ 921 ця1пч Буягею.сгпц; цяьпд Буягею.тьгеабгпч; ояьпч Буягею.ТЛгеабьпч.Таяля; с1аяя РШМССапсе10еюо ( згаСгс чогб Ма1п() ( Сапсе11аггопТосепбоцгсе сапсе1тосзгс = пен Сапсе11аг1оптоьепзоцгсе()г гпС[] с(аСа = пек гпС[10000000]; // Инициализировать массив данных положительными значениями. гог(гпС г=о; 1 < баса.сепчг)и 1++) бага[1] = ю // А теперь ввести в массив данных ряд отрицательных значений.
баса[1000] = -1; баса(140003 = -2) баса[15000] = -3; бага[б78000] = -4; бага[8024540! = -5; баса[9908000] = -б; О Использовать запрос РЩМО для поиска отрицательных значений. чаг печаг1чея = ггою ча1 ьп бага.ляРага11е1(). Хггьсапсе11аС1оп(сапсе1тоьзгс.тосеп) инесе ча1 < 0 яе1есг ча11 О Создать задачу для отмены запроса по истечении 100 ыиллисекунд. Таяь СаПСЕ1Тяс = Тая'К.раогссу.згаГСМЕН( () еь ( Тлгеаб.81еер(100)г сапсе1Тосзгс.Сапсе1()) ))' сгу ( Йогеасп(чаг ч ьп печаггчея) Сопво1е.Хггое(ч + " "); сагой(ОрегагьопСапсе1ебвхсерг1оп ехс) ( Сопяо1е.нгггесгпе(ехс.неяваче); сагой(Аччгечасевхсерсгоп ехс) ( Сопяо1е.
Хг1сеь1пе (ехс) 1 ) ггпа11у ( сапсе1твс.наТС(); сапсе1тоКБгс. 01ярояе () 1 сапсе1Тяь.озярояе(); ) Сопяо1е.игьгевьпе() 1 Ниже приведен результат выполнения этой программы. Если запрос отменяется до его завершения, то на экран выводится только сообщение об исключительной ситуации. Запрос отменен с помошью маркера, переданного в метод Х1СЛСапсе11аггоп.
922 Часть П. Библиотека С() Другие средства РИЙЯ Как упоминалось ранее, РЕ1)Х) ) представляет собой довольно крупную подсистему. Это объясняется отчасти той гибкостью, которой обладает Р1Л)Щ. В Р1.1МД доступны и многие другие средства, помогающие подстраивать параллельные запросы под конкретную ситуацию.