Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 157
Текст из файла (страница 157)
МуТЬгеаб шс1 пен МуТЬгеаб("Потомок В1")т МуТЬгеаб шс2 = печ МуТЬгеаб("Потомок В2")г МуТЬгеаб шГЗ = пен МуТЬгеаб("Потомок ВЗ")Г с(о ( Сопяо1е.иг1ге("."); Тпгеаб.Я1еер(100)г ) нЬ11е (шс1.Сочло < 10 (( шс2.Соппс < 10 шсз.соппс < 10)г Сопяо1е.иг1се11пе("Основной поток завершен."); Ниже приведен один из возможных результатов выполнения этой программы. Основной поток начат.
.Потомок В1 начат. Потомок В2 начат. Потомок ВЗ начат. 794 Часть и. Библиотека Се ....В потоке Потомок 41, Соппк = О В потоке Потомок 42, Сонно О В потоке Потомок ФЗ, Соппк = О .....В потоке Потомок 41, Сонно 1 В потоке Потомок 42, Сопле = 1 В потоке Потомок 43, Сопок = 1 .....В потоке Потомок 41, Соппк = 2 В потоке Потомок 42, Соппк = 2 В потоке Потомок 43, Сонно 2 .....В потоке Потомок 41, Сонпк = 3 В потоке Потомок 42, Сонно 3 В потоке Потомок 43, Соппк = 3 .....
В потоке Потомок 41, Сопок = 4 В потоке Потомок 42, Соппк 4 В потоке Потомок ФЗ, Соппк = 4 .....В потоке Потомок 41, СоппС 5 В потоке Потомок 42, Соппк 5 В потоке Потомок 43, Соппк = 5 ..... В потоке Потомок 41, Соипк = б В потоке Потомок 42, Соппк б В потоке Потомок 43, Сонно = б .....
В потоке Потомок 41, Соппк = 7 В потоке Потомок 42, Сонно = 7 В потоке Потомок 43, Соппк 7 ..... В потоке Потомок 41, СоппС = 8 В потоке Потомок 42, Сонно = 8 В потоке Потомок 43, Сопок = 8 ..... В потоке Потомок 41, Соппк = 9 Поток 41 завершен. В потоке Потомок 42, Соппк = 9 Поток 42 завершен. В потоке Потомок 43, Сопок = 9 Поток 43 завершен. Основной поток завершен. Как видите, после того как все три потока начнут выполняться, они будут совместно использовать ЦП.
Приведенный выше результат может отличаться в зависимости от среды выполнения, операционной системы и других внешних факторов, влияющих на выполнение программы. Определение момента окончания потока Нередко оказывается полезно знать, когда именно завершается поток В предыдущих примерах программ для этой цели отслеживалось значение переменной соппс. Но ведь это далеко не лучшее и не совсем пригодное для обобщения решение.
Правда, в классе ТЬсеас) имеются два других средства для определения момента окончания потока С этой целью можно, прежде всего, опросить доступное только для чтения свойство 18А11че, определяемое следу)ощим образом: риЬ11с Ьоо1 гза11те ( ОеС1 ) Свойство 18Д11зе возвращает логическое значение сгпе, если поток, для которого онп вызывается, по-прежнему выполняется. Для опробования свойства гзй11те под- Глава 2Э. Многопоточное программирование 795 ставьте приведенный ниже фрагмент кода вместо кода в классе могетЬгеаб в предыду- щей версии многопоточной программы. // Использовать свойство 1за11че для отслеживания // момента окончания потоков.
с1аяя МогеТЬгеабя ( ясас1с чо1б Магп() ( Сопзо1е.иггсепгпе("Основной поток начат."); // Сконструировать три потока. МуТЬгеаб шс1 = пем МуТЬгеаб("Поток $1")т МуТЬГЕаб ШГ2 = ПЕМ МуТЬГЕаб("ПОТОК В2ч)т МуТЬГЕаб ШГЗ ПЕМ МуТЬГЕаб("ПОТОК Фзч)т с(о ( Сопяо1е.нг1ге("."); ТЛгеаб .Я1еер (100) т ) мЬ11е (шс1.тпгб,гяа11че аа шг2.тьгб.1за1гче аа шт.З.ТЬгс(.1яа1).че)т Сопзо1е.нгьсеььпе("Основной поток завершен.") ) ) При выполнении этой версии программы результат получается таким же, как и прежде. Единственное отличие заключается в том, что в ней используется свойство Тзй11че для отслеживания момента окончания порожденных потоков.
Еще один способ отслеживания момента окончания состоит в вызове метода го1п () . Ниже приведена его простейшая форма. рпьтгс чотб до1п() Метод ЗО1п () ожидает до тех пор, пока поток, для которого он был вызван, не завершится. Его имя отражает принцип ожидания до тех пор, пока вызывающий поток не присоединится к вызванному методу. Если же данный поток не был начат, то генерируется исключение ТЬгеабзсасеихсерт1оп. В других формах метода до1п () можно указать мйксимальный период времени, в течение которого следует ожидать завершения указанного потока.
В приведенном ниже примере программы метод Зоап () используется для того, чтобы основной поток завершился последним. // Использовать метод Юоьп() пя1по Зуясеш; оя1пд Буясеш.ТЬгеаб1пдт с1аяя Мутпгеаб ( ровтгс гпс СоппГГ рпЬ11с ТЬгеаб тпгб; риЬ11с Мутьгеаб(ясг1по паве) ( Соопс = О," тьгб = пен ТЬгеаб(ЛЬгя.ппп)т ТЬгб.паше = пашет 796 Часть П. Библиотека С» ТЬгб.5сагс()к ) // Точка входа в поток. чогб Нип() ( Сопво1е.иггсепвпе(тпгб.наше т " начат."); бо ( тпгеаб.51еер(500); Сопво1е.иг1се11пе("В потоке " т Тпгб.наше т ", Соипс = " + Соспс); Соппстт; ) нЬ11е(сонпс < 10); Сопво1е.ИггсеЬгпе(ТЬгб.паше т " завершен."); ) ) // Использовать метод зогп() дпя ожидания до тех пор, // пока потоки не завершатся.
с1авв зогптпгеабв ( всас1с чогб Ма1п() ( Сопво1е.нггсе11пе("Основной поток начат.")) // Сконструировать три потока. МуТЬгеаб шг1 = пен МуТЬгеаб("Потомок $1")к МуТЬгеаб шс2 = пен МуТЬгеаб("Потомок ()2")к МуТЬгеаб шГЗ = пен МуТЬгеаб("Потомок $3")) шс1.ТЬгб. )огд()) Сопво1е.Иг1сепапе("Потомок Ф1 присоединен."); шг2.ТЬгб.зо1п Н ) Сопво1е.иггсептпе("Потомок $2 присоединен."); шГЗ. Тпгб.зо1п () ) Сопво1е.игггеьгпе("Потомок ()3 присоединен."); Сопво1е.иг1ге11пе("Основной поток завершен."); ) ) Ниже приведен один из возможных результатов выполнения этой программы. Напомним, что он может отличаться в зависимости от среды выполнения, операционной системы и прочих факторов, влияюп(их на выполнение программы.
Основной поток начат. Потомок к1 начат. Потомок ()2 начат. Потомок $3 начат. В потоке Потомок ()1, В потоке Потомок ()2, В потоке Потомок $3, В потоке Потомок ()1, В потоке Потомок ()2, В потоке Потомок $3, соппс Соипс Сочпс Сочпс Сочпс Соипс = 0 = 0 = 0 = 1 = 1 = 1 Глава 23. Многопоточное программирование 797 Как видите, после возврата из последовательного ряда вызовов метода Юо1п(] выполнение потоков завершилось. Передача аргумента потоку Первоначально в среде .)ч)ЕТ Егащезгог)г нельзя было передавать аргумент потоку, когда он начинался, поскольку у метода, служившего в качестве точки входа в поток, не могло быть параметров. Если же потоку требовалось передать какую-то информацию, то к этой цели приходилось идти различными обходными путями, например использовать общую переменную. Но этот недостаток был впоследствии устранен, и теперь аргумент может быть передан потоку.
Для этого придется воспользоваться другими формами метода ясагс (), конструктора класса ТПгеаг), а также метода, служащего в качестве точки входа в поток. Аргумент передается потоку в следующей форме метода ягагс (): ригътс чо1г) ягвгС(оЬЗесС агд) Объект, указываемый в качестве аргумента агд, автоматически передается методу, выполняющему роль точки входа в поток. Следовательно, для того чтобы передать аргумент потоку, его достаточно указать в качестве аргумента метода ягагс () . В потоке Потомок 41, Сонпг В потоке Потомок 42, Соппг В потоке Потомок 43, Соипг В потоке потомок 41, соппс В потоке Потомок 42, СоппС В потоке Потомок 43, СоппС В потоке Потомок 41, Соппг В потоке Потомок 42, Сонпг В потоке Потомок 43, Соипг В потоке Потомок 41, Соппг В потоке Потомок 42, Соппг В потоке Потомок 43, Соппг В потоке Потомок 41, Соппг В потоке Потомок 42, Совпг В потоке Потомок 43, Соппг В потоке Потомок 41, Соппг В потоке Потомок 42, Соппг В потоке Потомок 43, СоппС В потоке потомок 41, соппс В потоке Потомок 42, Совпг В потоке Потомок 43, СоппС В потоке Потомок 41, Сонпг Потомок 41 завершен.
В потоке Потомок 42, Соипг Потомок 42 завершен. В потоке Потомок 43, Соппг Потомок 43 завершен. Потомок 41 присоединен. Потомок 42 присоединен. Потомок 43 присоединен. Основной поток завершен. = 2 =г = 2 = 3 =з =з = 4 = 5 = 5 = 5 = б = б = б = 7 = 7 = 7 = 8 = 8 =8 = 9 798 Часть и, Библиотека С№ Для применения параметризированной формы метода Ягагг О потребуется следующая форма конструктора класса ТЬгеаб: роЫТс Тпгеаб(рагаиесегткебТЬгеабЯГагк точка входа) где точка входа обозначает метод, вызываемый с целью начать выполнение потока. Обратите внимание на то, что в этой форме конструктора точка входа имеет тип Рагаыегег1хебтвгеабЯГагс, а не ТЬгеас(ЯГагс, как в форме, использовавшейся в предыдущих примерах.
В данном случае Рагаиесег№хебТЬгеабягагг является делегатом, объявляемым следующим образом: роытс бе1едвге чо1б Рагакегегагебтьгеабзгагг(оь№есс агд) Как видите, этот делегат принимает аргумент типа ОЬ1есс. Поэтому для правильного применения данной формы конструктора класса твгеаб у метода, служащего в качестве точки входа в поток, должен быть параметр типа ОЬ1есс. В приведенном ниже примере программы демонстрируется передача аргумента потоку // Пример передачи аргумента методу потока.
ов1пд Яувгегн оз1пд 5увсеи.ТЬгеаб1пдт с1авв МуТЬгеаб ( роЬ11с 1пс Соопс) роЬ11с ТЬгеаб ТЬгс(т // Обратите внимание на го, что конструктору класса // мутЬгеаб передается также значение типа 1пс. роЬ11с МуТЬгеаб(всг1пд паве, 1пс пои) ( Соопс = От // Вызвать конструктор типа РагаиесвгхгебТЬгеабзсагс // явным образом только ради наглядности примера. тьгб = пеи тьгеаб(гь1в.аоп)т ТЬгб.иаие = папе; // Здесь переменная оои передается методу 5сагс() // в качестве аргумента. Тпгб.5сагс(пои)т // Обратите внимание на то, что в этой форме метода // Воп() указывается параметр типа оЬ№есс. чотб аоп(оЬ№есг пои) ( Сопво1е.нгвсеъхпе(ТЬгб.паве в " начат со счета " + пои)т к(о ( ТЬгеаб.51еер(500)т Сопво1е.нгтгеъъпе("В потоке " + ТЬгб.Наив + ", Соипг = " + Соопс)т Соипг++) ) нЫ1е (Соопс < (гос) пни) т Глава 23.
Многопоточное программирование 799 Сопзо1е.игьгепьпе(ТЬгб.паше т " завершен.") г ) ) с1азз РаззлгдПешо ( зсасьс тоьб Маьп() ( // Обратите внимание на то, что число повторений // передается этим дзум объектам типа МуТЬгеаб. МуТЬгеаб шс = пеи МуТЬгеаб("Потомок $1", 5); МуТЬгеаб шс2 = пен МуТЬгеаб("Потомок Е2", 3); бо ( тьгеаб.з1еер(100)) ) иЬ11е (шс.тьгб.1зА11те ( шс2.ТЬгб.1зА11те); Соозо1е.иг1сег Тпе("Основной поток завершен.") ) Ниже приведен результат выполнения данной программы, хотя у вас он может оказаться несколько иным.