Г. Шилдт - С#4.0 Полное руководство (1160795), страница 168
Текст из файла (страница 168)
топ) Впп() ( Сопяо1е.игггесьпе(ТЬгб.наше + " начат."); с)о ( ТЬгеаб.Я1еер(500)1 сопво1е.игтсевтпе("В потоке " + тьгб.иаве + ", соппс = " + соппс); соппсе+с НЬ11Е(СОППС < 10) 1 Сопяо1е.игсге11пе(ТЬгб.наве + " завершен."); ) ) с1аяв МогеТЬгеабя ( ягагтс чо1б Маго() ( Сопяо1е.игТСесьпе("Основной поток начат."); О Сконструировать три потока. МуТЬгеаб вС1 = пен МуТЬгеаб("Потомок ()1"); МуТЬгеаб вг2 = пен МуТЬгеаб("Потомок ()2")," МуТЬгеаб вСЗ = пем МуТЬгеаб("Потомок ()3"); с)о Сопяо1е.игтге(".")С ТЬгеаб.з1еер(100); ) ИЫ1е (вг1.СоппС < 10 вг2.Соппг < 10 вСЗ.Соппг < 10) 1 Сопяо1е.иг1Се)гпе("Основной поток завершен.")! ) Ниже приведен один из возможных результатов выполнения этой программы Основной поток начат. .Потомок ))1 начат.
Потомок ()2 начат. Потомок ()3 начат. ....В потоке Потомок ()1, Соппг = 0 В потоке Потомок ()2, Соппт = 0 В потоке Потомок ()3, Соппг = 0 Глава 23. Многопоточное программирование. Часть первая: основы 841 .....В потоке Потомок $1, Сооог = 1 В потоке Потомок $2, Сооог = 1 В потоке Потомок $3, Соопв = 1 .....В потоке Потомок $1, Сооог = 2 В потоке Потомок $2, Сооог = 2 В потоке Потомок $3, Соопг = 2 .....В потоке Потомок $1, Сооог = 3 В потоке Потомок $2, Сосок = 3 В потоке Потомок $3, Соопг = 3 В потоке Потонок $1, Сосок = 4 В потоке Потомок $2, Соопс = 4 В потоке Потомок $3, Соопг = 4 .....В потоке Потомок $1, Сооог = 5 В потоке Потомок $2, Соовс = 5 В потоке Потомок $3, Соовг = 5 В потоке Потомок $1, Сооог = б В потоке Потомок $2, Сооог = б В потоке Потомок $3, Соопс = б В потоке Потомок $1, Сонно = 7 В потоке Потомок $2, Соовс = 7 В потоке Потомок $3, Сосет = 7 В потоке Потомок $1, Соопг = 8 В потоке Потомок $2, Соопс = 8 В потоке Потомок $3, Соопг = 8 В потоке Потомок $1, Соопг = 9 Поток $1 завершен.
В потоке Потомок $2, Соовс = 9 Поток $2 завершен. В потоке Потомок $3, Соопг = 9 Поток $3 завершен. Основной поток завершен. Как видите, после того как все три потока начнут выполняться, они будут совместно использовать ЦП. Приведенный выше результат может отличаться в зависимости от среды выполнения, операционной системы и других внешних факторов, влияющих на выполнение программы.
Определение момента окончания потока Нередко оказывается полезно знать, когда именно завершается поток. В предыдущих примерах программ для этой цели отслеживалось значение переменной Сорос. Но ведь это далеко не лучшее и не совсем пригодное для обобщения решение.
Правда, в классе ТЬгеагЗ имеются два других средства для определения момента окончания потока. С этой целью можно, прежде всего, опросить доступное только для чтения свойство 18А11че, определяемое следующим образом. роЬ11с Ьоо1 1*81гте 1 чевм ) Свойство 1ВЛ11че возвращает логическое значение Ьгне, если поток, для которого оно вызывается, по-прежнему выполняется.
Для "опробования" свойства 18А11че подставьте приведенный ниже фрагмент кода вместо кода в классе Могетпгеап из предыдущей версии многопоточной программы, как показано ниже. 842 Часть (1. Библиотека С() // Использовать свойство гяА11че для отслеживания момента окончания потоков. с1аяя МогеТЬгеабя ( ятаттс чоЫ Ма1п() ( Сопяо1е.нтттеЬтпе("Основной поток начат.")1 // Сконструировать три потока. МуТЬгеаб вт1 = пен МуТЬтеаб("Поток №1") МуТЬгеаб вт2 = пем МуТЬгеаб("Поток №2") МуТЬтеаб втз = пен МуТЬгеаб("Поток №3") бо сопяо1е.хт1ге(".") г ТЬгеаб.Я1еер(100); ) нЬ11е (вт1,ТЬтб.1яА1тче ая вт2.ТЬтб.1яА1тче ья вГЗ.ТЬгб.1яА1тче); Сопяо1е.нт1тешпе("Основной поток завервен."); ) При выполнении этой версии программы результат получается таким же, как и прежде.
Единственное отличие заключается в том, что в ней используется свойство 1зА11че для отслеживания момента окончания порожденных потоков. Еще один способ отслеживания момента окончания состоит в вызове метода яо№ь ( ) . Ниже приведена его простейшая форма. рпЫ1с чоЫ зогп() Метод о отп ( ) ожидает до тех пор, пока поток, для которого он был вызван, не завершится. Его имя отражает принцип ожидания до тех пор, пока вызывающий поток не присоединится к вызванному методу.
Если же данный поток не был начат, то генерируется исключение ТЬгеабЯСатеЕхсерт1оп. В других формах метода Яоьп () можно указать максимальный период времени, в течение которого следует ожидать завершения указанного потока. В приведенном ниже примере программы метод 001п () используется для того, чтобы основной поток завершился последним. // Использовать метод зотп() оя1пд Яуятеьн пя1пс Яуятев.ТЬгеабтпгн с1аяя Мутптеаб ( рпшгс Тпт Сочпг; риЫ1с ТЬгеаб ТЬгс(; рпЬ1тс МуТЬтеаб(яггтпч паве) ( Сопят = 01 тьтб = пем тьтеаб(гь1я.нпп)г ТЬгг(.иаве = пагаег ТЬтб.ЯГатт()) ) Точка входа в поток.
чоЫ Рпп () ( Глава 23. Многопоточное программирование. Часть первая: основы 843 Сопяо1е.нггсеь1пе(тдгг).наше а " начат."); г)о ( тдгеаб.я1еер(500)) Сопяа1е Хг1сеьгпе("В потоке " + Т»»гг».Наше + ", Сонпс = " + Сопля); Сопля+а; ) и)»11е(сопля < 10)» Сопяо1е.иг»се01пе(т)»гг).паве ь " завершен.") // Использовать метод зо1п() для ожидания до тех пор, О пока потоки не завершатся.
с1аяя Оогптпгеаг)я ( яса11с чогб Ма1п() ( Сопяо1е.нг1се01пе("Основной поток начат.")1 // Сконструировать три потока. Мутьгеа») вс1 = пен Мут)тгеаг)("Потомок ()1")) Иут)тгеаг) вс2 = пен Иутпгеаб("Потомок ()2")» Мут)ггеаб вГЗ = пен Мут)тгеа»)("Потомок ФЗ")» вс1.Т)тго.того(); Сопяо1е.нг1ге11пе("Потомок $1 присоединен.")» всг.т» ).тотп(); Сопяо1е.иг1ге) Тпе("Потомок ()2 присоединен."); вгЗ.ТДгс).Зо1п()) Сопяо1е.нггсеь»пе("Потомок ()3 присоединен."): Сопяо1е.Хггсе) ьпе("Основной поток завершен.") Основной поток начат. Потомок ()1 начат.
Потомок Гг начат. Потомок ФЗ начат. В потоке Потомок Г1, В потоке Потомок $2, В потоке Потомок ГЗ, В потоке Потомок Г1, В потоке Потомок Фг, В потоке Потомок ФЗ, В потоке Потомок $1, В потоке Потомок ()2, В потоке Потомок ()3, В потоке Потомок $1, В потоке Потомок $2, Сопля = 0 Сопля = 0 Сопля = 0 Сопля = 1 Сопля = 1 Соппс = 1 Сопля = 2 Сопля = 2 Сочпс = 2 Сопля = 3 Сопля = 3 Ниже приведен один из возможных результатов выполнения этой программы.
Напомним, что он может отличаться в зависимости от среды выполнения, операционной системы и прочих факторов, влияющих на выполнение программы. 844 Часть!(. Библиотека С№ В потоке Потомок ФЗ, Соппс = 3 В потоке Потомок 41, Соапп = 4 В потоке Потомок 42, Соппс = 4 В потоке Потомок 43, Сопок = 4 В потоке Потомок 41, Соппс = 5 В потоке Потомок 42, Соппс = 5 В потоке Потомок 43, Соипп = 5 В потоке Потомок $1, Соппп = б В потоке Потомок 42, Соппг = б В потоке Потомок 43, Соопб = б В потоке Потомок 41, Соопс = 7 В потоке Потомок 42, Соопс = 7 В потоке Потомок 43, Сопок = 7 В потоке Потомок 41, Соопс = 8 В потоке Потомок 42, Соппс = В В потоке Потомок $3, Соопс =- В В потоке Потомок 41, Соипб = 9 Потомок 41 завершен.
В потоке Потомок 42, Соопп = 9 Потомок 42 завершен. В потоке Потомок 43, Соипс = 9 Потомок ФЗ завершен. Потомок 41 присоединен. Потомок 42 присоединен. Потомок ФЗ присоединен. Основной поток завершен. Как видите, выполнение потоков завершилось после возврата из последовательного ряда вызовов метода Поьп ( ) .
Передача аргумента потоку Первоначально в среде .)5)ЕТ Егатегног)4 нельзя было передавать аргумент потоку, когда он начинался, поскольку у метода, служившего в качестве точки входа в поток, не могло быть параметров. Если же потоку требовалось передать какую-то информацию, то к этой цели приходилось идти различными обходными путями, например использовать общук1 переменную. Но этот недостаток был впоследствии устранен, и теперь аргумент может быть передан потоку. Для этого придется воспользоваться другими формами метода Беате (), конструктора класса Т)тгеас(, а также метода, служащего в качестве точки входа в поток.
Аргумент передается потоку в следующей форме метода Беате () . ро511о нога БГагс(оЬЗесг параметр) Объект, указываемый в качестве аргумента параметр, автоматически передается методу, выполняющему роль точки входа в поток. Следовательно, для того чтобы передать аргумент потоку, достаточно передать его методу Беате () . Для применения параметризированной формы метода Бсагс () потребуется следующая форма конструктора класса тьгеас(: роЫ1о тьгеаг((рагашесег1вег(тьгеаг(БГагс запуск) где запуск обозначает метод, вызываемый с целью начать выполнение потока.
Обратите внимание на то, что в этой форме конструктора запуск имеет тип Глава 23. Многопоточное программнрованне. Часть первая: основы 848 РагатесегагебТЬгеабБЬагс, а не ТЬгеабБЬагс, как в форме, использовавшейся в предыдущих примерах. В данном случае Рагатесег1гебТЬгеабБСагб является делегатом, объявляемым следующим образом. роЫТс бе1еЧасе човб РагатесегьгебТЬгеабвсагя(оЬ)ест обу) Как видите, этот делегат принимает аргумент типа оЬЯ ес Ь. Поэтому для правильного применения данной формы конструктора класса ТЬгеаб у метода, служащего в качестве точки входа в поток, должен быть параметр типа ОЬЗ есс. В приведенном ниже примере программы демонстрируется передача аргумента потоку.