Г. Шилдт - С#4.0 Полное руководство (1160795), страница 176
Текст из файла (страница 176)
Библиотека С№ Сопво1е.игггевьпе("Основной поток прерван."); Эта программа дает следующий результат. Мой Поток начат 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ЗЗ 34 35 36 37 38 39 40 Прерывание потока. Поток прерван, код завершения 100 Основной поток прерван. Как следует из приведенного выше результата, значение 100 передается методу АЬогс () в качестве кода прерывания. Это значение становится затем доступным посредством свойства ехсерг1опягаге из класса исключения тьгеабйьоггнхсерг1оп, которое перехватывается потоком при его прерывании. Отмена действия метода дЬог~ () Запрос на преждевременное прерывание может быть переопределен в самом потоке. Для этого необходимо сначала перехватить в потоке исключение ТЬгеабАЬогснхсерстоп, а затем вызвать метод ПеяеГАЬогс () .
Благодари этому исключается повторное генерирование исключения по завершении обработчика исключения, прерывающего данный поток. Ниже приведена форма объявления метода РеяеГАЬогс () . роЫ1с ясас1с ногб ПевеГЛЬогс0 Вызов метода ПеяеГАЬогс () может завершиться неудачно, если в потоке отсутствует надлежащий режим надежной отмены преждевременного прерывания потока. В приведенном ниже примере программы демонстрируется применение метода ПеяеГАЬогс () . О Использовать метод НевеГАЬогс() пягпд яуясевГ пя1по Яуясет.ТЛгеаб1пог с1авя Мутйгеаб ( рпЫ1С ТПГЕаб ТПГбГ рпЫ1с МуТпгеаб(ясггпч паве) Тьгб = пен Тдгеаб(гЫя.йпп)г Тйгб.нате = паве) Тлгб.ясагс(); О Это точка входа в поток. но1б Нчп() ( Сопяо1е.иггсевьпе(ТПгб.нате т " начат."); Гог(1пг 1 = 16 1 <= 1000) 1++) Глава 23.
Многопоточное программирование. Часть первая: основы 879 агу ( Сопяо1е.нгтяе(г + " "); Г Е ( (1ь10)==0) ( Сопяо1е. ХгтсеЬ1пе () ) тдгеаб.81еер(250)," сассЬ(тдгеабЧЬогсвхсерт1оп ехс) ( 18((тпс)ехс.вхсерг1опБСате == 0) ( Сопяо1е.нгтсеЬгпе("Прерывание потока отменено! "код завершения " + ехс.ехсерг1опзгаге); тьгеаб.пеяеГАЬогг()г ) е1яе сопво1е.хгтгеьгпе("поток прерван, код завершения " ь ехс.Ехсерсбопзсасе)7 Сопяо1е.нггсеЬгпе(ТЬгб.наше + " завершен нормально."); ) с1аяя Пеяегльогс ( ясастс чотб Мати() ( МуТЬгеаб шс1 = пеи МуТЬгеаб("Мой Поток" ); Тьгеаб.81еер(1000)г // разрешить порожденному потоку начать свое выполнение Сопяо1е .Хгт яет Еле (" Прерывание потока. ") ) ша1.ТЬгб.АЬогг(0); О зто не остановит поток Тагеаб.81еер(1000); О разрешить порожденному потоку выполняться подольше Сопяо1е.нгтсеЬ1пе("Прерывание потока."); шг1.ТЬгб.АЬогс(100); О а зто остановит поток шс1.ТЬгб.зотп()г // ожидать прерывания потока Сопяо1е.нг1сеЬТпе("Основной поток прерван.") ) Ниже приведен результат выполнения этой программы.
Мой Поток начат 1 2 3 4 5 б 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 Зб 37 38 39 40 Прерывание потока. Прерывание потока отменено! Код завершения 0 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 Поток прерван, код завершения 100 Основной поток прерван.
880 Час)ъ (1. Библиотека С() Если в данном примере программы метод АЬогг. () вызывается с нулевым аргументом, то запрос на преждевременное прерывание отменяется потоком, вызывающим метод РеяесАЬогс (), и выполнение этого потока продолжается. Любое другое значение аргумента приведет к прерыванию потока. Приостановка и возобновление потока В первоначальных версиях среды .)1ЕТ Ргатеьчог)с поток можно было приостановить вызовом метода ТЬгеаб. Биярепб () и возобновить вызовом метода ТЬгеаб.
Везшее ( ) . Но теперь оба эти метода считаются устаревшими и не рекомендуются к применению в новом коде. Объяснлется это, в частности, тем, что пользоватьсл методом Яиярепб ( ) на самом деле небезопасно, так как с его помощью можно приостановить поток, который в настолщий момент удерживает блокировку, что препятствует ее снятию, а следовательно, приводит к взаимоблокировке. Применение обоих методов может стать причиной серьезных осложнений на уровне системы. Поэтому для приостановки и возобновления потока следует использовать другие средства синхронизации, в том числе мьютекс и семафор.
Определение состояния потока Состояние потока может быть получено из свойства ТЬгеабэгаге, доступного в классе тЬгеаб. Ниже приведена общая форма этого свойства. роЫЬс тьгеабзсасе тьгеабзсаге( дегг ) Состояние потока возвращаетсл в виде значения, определенного в перечислении тьгеабэсасе. Ниже приведены значения, определенные в этом перечислении. ТЬгеабэгаге.АЬоггеб ТпгеабЯСаге.АЬоггнес(иеягеб ТЬгеабэгаге.нипптпц ТЬгеабэгаге.Васкгггоппб ТЬгеабэгаге.БСорреб ТЬгеабэгаге.эгорпег)цеягеб ТЬгеабэгаге.эиярепбрес(иеягеб ТЬгеабэгаге.иатгэтеерлотп ТЬгеабБСаге.эпярепбеб ТЬгеабБСаге.ппягаггеб Все эти значения не требуют особых пояснений, за исключением одного.
Значение тьгеабБ гасе . иатсБтеероотп обозначает состояние, в которое поток переходит во время ожидания в связи с вызовом метода Иатг (), Бтеер () или дотп () . Применение основного потока риЫтс ягасгс Тьгеаб Соггепгтьгеаб( дес; ) Как пояснялось в самом начале этой главы, у всякой программы на С() имеется хотя бы один поток исполненил, называемый основным. Этот поток программа получает автоматически, как только начинает выполняться. С основным потоком можно обращаться таким же образом, как и со всеми остальными потоками. Для доступа к основному потоку необходимо получить объект типа тпгеаб, который ссылается на него.
Это делается с помощью свойства сцггепгтпгеаб, являющегося членом класса ТЬгеаб. Ниже приведена общая форма этого свойства. Глава 23. Многопоточное программирование. Часть первая: основы 885. Данное свойство возвращает ссылку на тот поток, в котором оно используется.
Поэтому если свойство СпггепСТЛгеас) используется при выполнении кода в основном потоке, то с его помощью можно получить ссылку на основной поток. Имея в своем распоряжении такую ссылку, можно управлять основным потоком так же, как и любым другим потоком. В приведенном ниже примере программы сначала получается ссылка на основной поток, а затем получаются и устанавливаются имя и приоритет основного по~ока. О Продемонстрировать управление основным потоком. овгпо Яувгегм оаьпд Бувсеи.тьгеаг(гпч; с1авв Пвемвгп всасгс то1О Маьп() ( ТЬ аа тд Получить основной поток. Тпгг) = Тьгеаб.соггепстьгеасй Отобразить имя основного потока.
11(ТЬго.пате == по11) Сопво1е.нг1оеь1пе("У основного потока нет имени."); е1ве Сопво1е.Хг1оевьпе("Основной поток называется: " + Тьгс.иные) О Отобразить приоритет основного потока. Сопво1е.нг1сеЬТпе("Приоритет: " + ТЛгО.Рг1огьсу) Сопво1е.нггсевгпе(); Установить имя и приоритет. Сопво1е.Хггсе11пе (" Установка имени и приоритета . 1п") г Тьгб.Хаме = "Основной Поток"; Тдгь).рг1ог1гу = Тпгеадрг1ог1гу.ВЬоиепогта1г Сопво1е.нггсеЬ1пе("Теперь основной поток называется: тьгс.иа е): Сопво1е.нггсеьдпе("Теперь приоритет: " + Тпгг).Рг1ог1су); ) ) Ниже приведен результат выполнения этой программы.
У основного потока нет имени. Приоритет: Ногыа1 Установка имени и приоритета. Теперь основной поток называется: Основной Поток Теперь приоритет: ЬЬотеногиа1 Следует, однако, быть очень внимательным, выполняя операции с основным потоком. Так, если добавить в конце метода Маги ( ) следующий вызов метода ПО 1п ( ); ТЬ 1. )о () ." программа никогда не завершится, поскольку оиа будет ожидать окончания основного потока! 882 Часть! 1. Библиотека С№ Дополнительные средства многопоточной обработки, внедренные в версии .НЕТ ГгагпевогК 4.0 В версии .)Х)ЕТ Ргашеьгог)с 4.0 внедрен ряд новых средств многопоточной обработки, которые могут оказаться весьма полезными. Самым важным среди них является новая система отмены. В этой системе поддерживается механизм отмены потока простым, вполне определенным и структурированным способом.
В основу этого механизма положено понятие признака отмени, с помощью которого указывается состояние отмены потока. Признаки отмены поддерживаются в классе Сапсе11ас1опТокепэоигсе и в структуре Сапсе11ас1оптокеп. Система отмены полностью интегрирована в новую библиотеку распараллеливания задач (ТРЕ), и поэтому она подробнее рассматривается вместе с ТРЕ в главе 24. В класс эуз ьет. тпгеас(1по добавлена структура эрьпиаьь, предоставляющая методы эрьпопсе ( ) и ярьпнпь11 (), которые обеспечивают более полный контроль над ожиданием в состоянии занятости. Вообще говоря, структура ЯР1пиаТЬ оказывается непригодной лля однопроцессорных систем.
А Лля многопроцессорных систем она применяется в цикле. Еще одним элементом, связанным с ожиданием в состоянии занятости, является структура Брьпьоск, которая применяется в цикле ожидания до тех пор, пока не станет доступной блокировка. В класс ТЬгеаг( добавлен метод Хае1с( (), который просто выдает остаток кванта времени, выделенного потоку. Ниже приведена общая форма объявления этого метода. ришьс згасгс Ьсз1 Х1е1г) 0 Этот метод возвращает логическое значение Ьгсе, если происходит переключение контекста.
В отсутствие другого потока, готового для выполнения, переключение контекста не произойдет. Рекомендации по многопоточному программированию Для эффективного многопоточного программирования самое главное — мыслить категориями параллельного, а не последовательного выполнения кода. Так, если в одной программе имеются две подсистемы, которые могут работать параллельно, их следует организовать в отдельные потоки. Но делать это следует очень внимательно и аккуратно, поскольку если создать слишком много потоков, то тем самым можно значительно снизить, а не повьюить производительность программы.