Главная страница
Навигация по странице:

  • Результат выполнения программы (из листинга 6.3)

  • Результат выполнения программы (из листинга 6.4)

  • Операции с потоками

  • Васильев А.Н. Основы программирования на C#. Васильев А. Н. Программирование


    Скачать 5.54 Mb.
    НазваниеВасильев А. Н. Программирование
    АнкорВасильев А.Н. Основы программирования на C
    Дата20.09.2022
    Размер5.54 Mb.
    Формат файлаpdf
    Имя файлаVasilev_Programmirovanie-na-C-dlya-nachinayushchih-Osobennosti-y.pdf
    ТипДокументы
    #686596
    страница23 из 40
    1   ...   19   20   21   22   23   24   25   26   ...   40
    Результат выполнения программы (из листинга 6.2)
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: ɇɚɱɚɥɨ...
    ɉɨɬɨɤ A: ɇɚɱɚɥɨ...
    Глава 6
    286
    ɉɨɬɨɤ B: ɇɚɱɚɥɨ...
    ɉɨɬɨɤ B -> 1
    ɉɨɬɨɤ C: ɇɚɱɚɥɨ...
    ɉɨɬɨɤ A -> 1
    ɉɨɬɨɤ C -> 1
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: Ɂɚɜɟɪɲɟɧɢɟ...
    ɉɨɬɨɤ C -> 2
    ɉɨɬɨɤ B -> 2
    ɉɨɬɨɤ A -> 2
    ɉɨɬɨɤ C -> 3
    ɉɨɬɨɤ B -> 3
    ɉɨɬɨɤ C -> 4
    ɉɨɬɨɤ B -> 4
    ɉɨɬɨɤ A -> 3
    ɉɨɬɨɤ C -> 5
    ɉɨɬɨɤ B -> 5
    ɉɨɬɨɤ C -> 6
    ɉɨɬɨɤ B -> 6
    ɉɨɬɨɤ A -> 4
    ɉɨɬɨɤ C -> 7
    ɉɨɬɨɤ C -> 8
    ɉɨɬɨɤ B: Ɂɚɜɟɪɲɟɧɢɟ...
    ɉɨɬɨɤ A -> 5
    ɉɨɬɨɤ C: Ɂɚɜɟɪɲɟɧɢɟ...
    ɉɨɬɨɤ A: В этой программе в главном потоке создаются три дочерних потока. Дочерние потоки создаются на основе нестатического метода show(), описанного в классе MyClass. У класса MyClass есть закрытое целочисленное поле count
    , определяющее количество сообщений (не считая начального и конечного, отображаемых в дочернем потоке

    Многопоточное программирование закрытое целочисленное поле time
    , определяющее время приостановки выполнения потока текстовое поле text
    , значение которого определяет текст сообщений, отображаемых в потоке.
    Значения полей передаются аргументами конструктору при создании объекта и используются в методе show(). В теле конструктора командой
    Console.WriteLine(text+
    Ǝ: ɇɚɱɚɥɨ...Ǝ) выводится сообщение о начале выполнения метода (потока. Затем запускается оператор цикла (количество итераций цикла определяется значением поля count), и на каждой итерации командой Console.WriteLine(text+
    Ǝ -> Ǝ+i) отображается сообщение. Для задержки в выполнении потока использована команда Thread.Sleep(time). После завершения оператора цикла командой Console.WriteLine(text+
    Ǝ: Ɂɚɜɟɪɲɟɧɢɟ...Ǝ) отображается сообщение о завершении выполнения метода (и, следовательно, потока).
    В главном методе отображается сообщение о начале выполнения главного потока (команда Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ: ɇɚ-
    ɱɚɥɨ...Ǝ)). Далее создаются три объекта objA, objB и objC класса
    MyClass
    . Это обычные объекты. На их основе создаются объекты дочерних потоков A, B и C. Каждый раз аргументом конструктору класса
    Thread передается ссылка на метод show() объекта класса MyClass инструкции objA.show, objB.show и objC.show). Для запуска каждого из потоков на выполнение из объекта потока вызывается метод
    Start()
    (команды A. Start(), B. Start() и C. Start()). В результате одновременно с выполнением главного потока в режиме дочерних потоков начинается выполнение кода метода show() из объектов
    A
    (первый дочерний поток, B (второй дочерний потоки (третий дочерний поток. В это время командой Console.WriteLine(
    ƎȽɥɚɜ-
    ɧɵɣ ɩɨɬɨɤ: Ɂɚɜɟɪɲɟɧɢɟ...Ǝ) в главном потоке выводится сообщение о завершении потока НАЗ А МЕТКУ Параметры, влияющие на выполнение потоков, подобраны так, что главный поток завершается раньше дочерних потоков. По умолчанию дочерние потоки являются приоритетными, поэтому продолжают работу даже при завершении главного потока. Позже мы познакомимся с фоновыми потоками, которые автоматически завершаются при завершении главного потока
    Глава Иногда возникает необходимость водном потоке (например, главном) выполнить определенную команду только после завершения другого потока. В таких случаях используют свойство IsAlive, которое возвращает значение true, если поток (для объекта, из которого запрашивается свойство) еще выполняется. Если поток завершен, значение свойства равно Вызов метода Join() означает ожидание завершения потока, из объекта которого вызван метод НАЗ А МЕТКУ Если вызвать метод
    Join()
    из объекта потока, который еще нестар- товал, генерируется исключение класса Программа, в которой используются свойство IsAlive и метод Join(), представлена в листинге Листинг 6.3. Координация завершения потоков System;
    using System.Threading;
    //
    Ƚɥɚɜɧɵɣ ɤɥɚɫɫ:
    class JoinDemo{
    //
    Ɇɟɬɨɞ ɞɥɹ ɞɨɱɟɪɧɟɝɨ ɩɨɬɨɤɚ:
    static void run(){
    Console.WriteLine(
    ƎȾɨɱɟɪɧɢɣ ɩɨɬɨɤ ɡɚɩɭɳɟɧ...Ǝ);
    //
    Ɉɩɟɪɚɬɨɪ ɰɢɤɥɚ:
    for(int k=1;k<=5;k++){
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɫɨɨɛɳɟɧɢɹ:
    Console.WriteLine(
    ƎȾɨɱɟɪɧɢɣ ɩɨɬɨɤ: Ǝ+k);
    //
    Ɂɚɞɟɪɠɤɚ ɜ ɜɵɩɨɥɧɟɧɢɢ ɩɨɬɨɤɚ:
    Thread.Sleep(2500);
    }
    Console.WriteLine(
    ƎȾɨɱɟɪɧɢɣ ɩɨɬɨɤ ɡɚɜɟɪɲɟɧ...Ǝ);
    }
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:

    Многопоточное программирование static void Main(){
    //
    ɇɚɱɚɥɶɧɨɟ ɫɨɨɛɳɟɧɢɟ ɝɥɚɜɧɨɝɨ ɩɨɬɨɤɚ:
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ ɡɚɩɭɳɟɧ...Ǝ);
    //
    Ɉɛɴɟɤɬ ɞɨɱɟɪɧɟɝɨ ɩɨɬɨɤɚ:
    Thread t=new Thread(run);
    //
    Ɂɚɩɭɫɤ ɞɨɱɟɪɧɟɝɨ ɩɨɬɨɤɚ:
    t.Start();
    //
    Ɉɩɟɪɚɬɨɪ ɰɢɤɥɚ:
    for(char s=
    ƍAƍ;s<=ƍFƍ;s++){
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɫɨɨɛɳɟɧɢɹ:
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ: Ǝ+s);
    //
    Ɂɚɞɟɪɠɤɚ ɜ ɜɵɩɨɥɧɟɧɢɢ ɩɨɬɨɤɚ:
    Thread.Sleep(1000);
    }
    //
    Ɉɠɢɞɚɧɢɟ ɡɚɜɟɪɲɟɧɢɹ ɞɨɱɟɪɧɟɝɨ ɩɨɬɨɤɚ:
    if(t.IsAlive) t.Join();
    //
    ɉɨɫɥɟɞɧɟɟ ɫɨɨɛɳɟɧɢɟ ɝɥɚɜɧɨɝɨ ɩɨɬɨɤɚ:
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ ɡɚɜɟɪɲɟɧ...Ǝ);
    Возможный результат выполнения программы представлен ниже:
    
    Результат выполнения программы (из листинга 6.3)
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ ɡɚɩɭɳɟɧ...
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ ɡɚɩɭɳɟɧ...
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ: 1
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: A
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: B
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: C
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ: 2
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: D
    Глава 6
    290
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: E
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ: 3
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: F
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ: 4
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ: 5
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ ɡɚɜɟɪɲɟɧ...
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ В главном методе программы запускается дочерний поток. В дочернем потоке выполняется статический метод run(). И дочерний, и главный потоки выводят в консольное окно сообщения. Параметры выполнения потоков подобраны таким образом, что главный поток выполняется значительно быстрее. Нов главном потоке размещен условный оператор, в котором проверяется значение свойства IsAlive объекта дочернего потока t. Если условие истинно (то есть если дочерний поток еще выполняется, то выполняется команда t.Join(). Выполнение команды приводит к тому, что главный поток ожидает выполнения дочернего потока, и только после этого в главном потоке выполняется команда
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ Следующая программа, представленная в листинге 6.4, иллюстрирует способ создания дочерних потоков на основе экземпляра делегата (имеется ввиду явное создание экземпляра делегата и его передача в качестве аргумента конструктору класса Thread), атак- жена основе лямбда-выражения (когда лямбда-выражение передается аргументом конструктору класса Листинг 6.4. Поток на основе экземпляра делегата System;
    using System.Threading;
    //
    Ʉɥɚɫɫ ɫ ɦɟɬɨɞɨɦ ɞɥɹ ɡɚɩɭɫɤɚ ɜ ɩɨɬɨɤɟ:
    class MyClass{
    //
    Ɂɚɤɪɵɬɨɟ ɬɟɤɫɬɨɜɨɟ ɩɨɥɟ:
    private string text;
    //
    Ɂɚɤɪɵɬɨɟ ɰɟɥɨɱɢɫɥɟɧɧɨɟ ɩɨɥɟ:
    private int time;

    Многопоточное программирование //
    Ʉɨɧɫɬɪɭɤɬɨɪ:
    public MyClass(string txt,int t){
    text=txt;
    time=t;
    }
    //
    Ɇɟɬɨɞ ɛɟɡ ɚɪɝɭɦɟɧɬɨɜ:
    public void show(){
    for(int k=1;k<=5;k++){
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɫɨɨɛɳɟɧɢɹ:
    Console.WriteLine(text+
    Ǝ\tƎ+k);
    //
    Ɂɚɞɟɪɠɤɚ ɜ ɜɵɩɨɥɧɟɧɢɢ ɩɨɬɨɤɚ:
    Thread.Sleep(time);
    }
    }
    }
    //
    Ƚɥɚɜɧɵɣ ɤɥɚɫɫ:
    class ThreadStartDemo{
    //
    ɋɬɚɬɢɱɟɫɤɢɣ ɦɟɬɨɞ ɫ ɞɜɭɦɹ ɚɪɝɭɦɟɧɬɚɦɢ:
    static void run(string txt,int time){
    for(int k=1;k<=5;k++){
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɫɨɨɛɳɟɧɢɹ:
    Console.WriteLine(txt+
    Ǝ\tƎ+k);
    //
    Ɂɚɞɟɪɠɤɚ ɜ ɜɵɩɨɥɧɟɧɢɢ ɩɨɬɨɤɚ:
    Thread.Sleep(time);
    }
    }
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:
    static void Main(){
    //
    ɇɚɱɚɥɶɧɨɟ ɫɨɨɛɳɟɧɢɟ ɜ ɝɥɚɜɧɨɦ ɩɨɬɨɤɟ:
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ ɡɚɩɭɳɟɧ...Ǝ);
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɨɜ ɤɥɚɫɫɚ MyClass:
    MyClass A=new MyClass(
    ƎɈɛɴɟɤɬ AƎ,1000);
    Глава 6
    292
    MyClass B=new MyClass(
    ƎɈɛɴɟɤɬ BƎ,1500);
    //
    ɋɨɡɞɚɧɢɟ ɷɤɡɟɦɩɥɹɪɚ ɞɟɥɟɝɚɬɚ:
    ThreadStart ts=A.show;
    //
    Ⱦɨɛɚɜɥɟɧɢɟ ɦɟɬɨɞɚ ɜ ɫɩɢɫɨɤ ɜɵɡɨɜɨɜ
    //
    ɷɤɡɟɦɩɥɹɪɚ ɞɟɥɟɝɚɬɚ:
    ts+=B.show;
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɩɨɬɨɤɚ ɧɚ ɨɫɧɨɜɟ ɷɤɡɟɦɩɥɹɪɚ
    //
    ɞɟɥɟɝɚɬɚ:
    Thread first=new Thread(ts);
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɩɨɬɨɤɚ ɧɚ ɨɫɧɨɜɟ
    //
    ɥɹɦɛɞɚ-ɜɵɪɚɠɟɧɢɹ:
    Thread second=new Thread(()=>{
    run(
    ƎɆɟɬɨɞ AlphaƎ,1200);
    run(
    ƎɆɟɬɨɞ BravoƎ,800);
    });
    //
    Ɂɚɩɭɫɤ ɩɟɪɜɨɝɨ ɩɨɬɨɤɚ:
    first.Start();
    //
    Ɂɚɩɭɫɤ ɜɬɨɪɨɝɨ ɩɨɬɨɤɚ:
    second.Start();
    //
    Ɉɠɢɞɚɧɢɟ ɨɤɨɧɱɚɧɢɹ ɜɵɩɨɥɧɟɧɢɹ ɩɟɪɜɨɝɨ ɩɨɬɨɤɚ:
    if(first.IsAlive) first.Join();
    //
    Ɉɠɢɞɚɧɢɟ ɨɤɨɧɱɚɧɢɹ ɜɵɩɨɥɧɟɧɢɹ ɜɬɨɪɨɝɨ ɩɨɬɨɤɚ:
    if(second.IsAlive) second.Join();
    //
    ɉɨɫɥɟɞɧɟɟ ɫɨɨɛɳɟɧɢɟ ɜ ɝɥɚɜɧɨɦ ɩɨɬɨɤɟ:
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ ɡɚɜɟɪɲɟɧ...Ǝ);
    Ниже показано, как может выглядеть результат выполнения программы:
    
    Результат выполнения программы (из листинга 6.4)
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ ɡɚɩɭɳɟɧ...
    Ɉɛɴɟɤɬ A 1

    Многопоточное программирование Alpha 1
    Ɉɛɴɟɤɬ A 2
    Ɇɟɬɨɞ Alpha 2
    Ɉɛɴɟɤɬ A 3
    Ɇɟɬɨɞ Alpha 3
    Ɉɛɴɟɤɬ A 4
    Ɇɟɬɨɞ Alpha 4
    Ɉɛɴɟɤɬ A 5
    Ɇɟɬɨɞ Alpha 5
    Ɉɛɴɟɤɬ B 1
    Ɇɟɬɨɞ Bravo 1
    Ɉɛɴɟɤɬ B 2
    Ɇɟɬɨɞ Bravo 2
    Ɇɟɬɨɞ Bravo 3
    Ɉɛɴɟɤɬ B 3
    Ɇɟɬɨɞ Bravo 4
    Ɇɟɬɨɞ Bravo 5
    Ɉɛɴɟɤɬ B 4
    Ɉɛɴɟɤɬ B 5
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ У насесть класс MyClass с методом show(), который выводит в консольное окно сообщения. Текст сообщения и задержка между сообщениями определяются полями объекта, из которого вызывается метод. При этому метода нет аргументов и метод не возвращает результат.
    В главном классе описан статический метод run(). Метод также выводит сообщения в консольное окно. Он не возвращает результат, ноу него два аргумента (текстовый и целочисленный. Аргументы определяют текст сообщений и задержку между этими сообщениями.
    В главном методе создаются объекты A и B класса MyClass. Командой мы создаем экземпляр ts делегата
    ThreadStart
    , который ссылается на метод show() объекта A. После этого командой ts+=B.show в список вызовов экземпляра делегата добавляется еще и ссылка на метод show() объекта B.
    Глава На основе экземпляра ts создается объект first для первого дочернего потока (команда Thread first=new Thread(ts)). При запуске этого потока командой first.Start() сначала вызывается метод show() из объекта A, а по завершении выполнения метода вызывается метод show()
    из объекта B.
    {
    i
    НАЗ А МЕТКУ Таким образом, в первом дочернем потоке сначала выполняется метод из объекта
    A
    , а затем выполняется метод show()
    из объекта Еще один дочерний поток создается на основе лямбда-выражения. При создании объекта second классу Thread аргументом передается такое лямбда-выражение:
    ()=>{
    run(
    ƎɆɟɬɨɞ AlphaƎ,1200);
    run(
    ƎɆɟɬɨɞ Это лямбда-выражение определяет метод без аргументов, при вызове которого последовательно вызывается метод run() с разными аргументами. Поэтому при запуске второго дочернего потока на выполнение командой second.Start() сначала вызывается метод run() с аргументами и 1200, а затем этот же метод run() вызывается с аргументами
    ƎɆɟɬɨɞ BravoƎ и 800.
    {
    i
    НАЗ А МЕТКУ Второй дочерний поток выполняется следующим образом сначала выполняется команда run("
    Ɇɟɬɨɞ
    Alpha",1200)
    , а после того как команда выполнена, выполняется команда run("
    Ɇɟɬɨɞ Перед отображением последнего сообщения в главном потоке ожидается выполнение первого и второго дочерних потоков

    Многопоточное программирование
    295
    Фоновые потоки
    Если мы допустим беспорядок в документации, потомки нам этого не простят.
    из к/ф Гостья из будущего»
    Как отмечалось ранее, если главный поток завершает работу, то дочерние потоки автоматически не завершаются. Такие дочерние потоки называются приоритетными. Однако есть категория потоков, которые называются фоновыми. Их особенность в том, что при завершении главного потока фоновые потоки завершаются автоматически.
    У каждого объекта потока есть свойство IsBackground. Свойство может принимать значение true или false. Если свойство IsBackground объекта потока равно true, то поток является фоновым. Если значение свойства IsBackground объекта потока равно false, то поток является приоритетным. По умолчанию значение свойства IsBackground для объектов потоков равно false, поэтому все потоки, которые мы создавали ранее, были приоритетными. Если мы хотим создать фоновый поток, то необходимо свойству IsBackground объекта этого потока присвоить значение true. Пример создания фонового потока представлен в программе в листинге Листинг 6.5. Фоновый поток System;
    using System.Threading;
    //
    Ʉɥɚɫɫ ɫ ɝɥɚɜɧɵɦ ɦɟɬɨɞɨɦ:
    class BackgroundDemo{
    //
    ɋɬɚɬɢɱɟɫɤɢɣ ɦɟɬɨɞ ɞɥɹ ɜɵɩɨɥɧɟɧɢɹ ɜ ɮɨɧɨɜɨɦ ɩɨɬɨɤɟ:
    static void run(){
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɫɨɨɛɳɟɧɢɹ:
    Console.WriteLine(
    ƎȾɨɱɟɪɧɢɣ ɩɨɬɨɤ ɡɚɩɭɳɟɧ...Ǝ);
    //
    ɐɟɥɨɱɢɫɥɟɧɧɚɹ ɩɟɪɟɦɟɧɧɚɹ:
    int k=1;
    Глава 6
    296
    //
    Ȼɟɫɤɨɧɟɱɧɵɣ ɰɢɤɥ:
    while(true){
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɫɨɨɛɳɟɧɢɹ:
    Console.WriteLine(
    ƎȾɨɱɟɪɧɢɣ ɩɨɬɨɤ: Ǝ+k);
    //
    ɍɜɟɥɢɱɟɧɢɟ ɡɧɚɱɟɧɢɹ ɩɟɪɟɦɟɧɧɨɣ:
    k++;
    //
    Ɂɚɞɟɪɠɤɚ ɜ ɜɵɩɨɥɧɟɧɢɢ ɩɨɬɨɤɚ:
    Thread.Sleep(2100);
    }
    }
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:
    static void Main(){
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɧɚɱɚɥɶɧɨɝɨ ɫɨɨɛɳɟɧɢɹ:
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ ɡɚɩɭɳɟɧ...Ǝ);
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɩɨɬɨɤɚ:
    Thread t=new Thread(run);
    //
    Ɏɨɧɨɜɵɣ ɩɨɬɨɤ:
    t.IsBackground=true;
    //
    Ɂɚɩɭɫɤ ɮɨɧɨɜɨɝɨ ɩɨɬɨɤɚ:
    t.Start();
    //
    Ɉɩɟɪɚɬɨɪ ɰɢɤɥɚ:
    for(char s=
    ƍAƍ;s<=ƍFƍ;s++){
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɫɨɨɛɳɟɧɢɹ:
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ: Ǝ+s);
    //
    Ɂɚɞɟɪɠɤɚ ɜ ɜɵɩɨɥɧɟɧɢɢ ɝɥɚɜɧɨɝɨ ɩɨɬɨɤɚ:
    Thread.Sleep(1000);
    }
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɩɨɫɥɟɞɧɟɝɨ ɫɨɨɛɳɟɧɢɹ:
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ ɡɚɜɟɪɲɟɧ...Ǝ);
    }
    }

    Многопоточное программирование
    297
    Возможный результат выполнения программы представлен ниже:
    
    Результат выполнения программы (из листинга 6.5)
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ ɡɚɩɭɳɟɧ...
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: A
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ ɡɚɩɭɳɟɧ...
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ: 1
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: B
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: C
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ: 2
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: D
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: E
    Ⱦɨɱɟɪɧɢɣ ɩɨɬɨɤ: 3
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ: F
    Ƚɥɚɜɧɵɣ ɩɨɬɨɤ Особенность этого примера в том, что метод run(), который выполняется в дочернем потоке, содержит бесконечный цикл (в операторе while условием указано true). Теоретически такой метод (или поток на его основе) должен был бы работать бесконечно. Но поток, который создается на основе метода run(), является фоновым. Он становится фоновым после выполнения команды t.IsBackground=true, где t является объектом потока. Поэтому после запуска (команда t.Start()) дочерний фоновый поток выполняется до тех пор, пока выполняется породивший его главный поток. При завершении главного потока дочерний фоновый поток завершается автоматически.
    Обычно фоновые потоки используются для решения вспомогательных задач.
    Операции с потоками
    Боже, какой типаж Браво, браво Слушайте, я не узнаю вас в гриме Кто вы такой?
    из к/ф Иван Васильевич меняет профессию»
    Существуют свойства и методы, которые позволяют выполнять различные операции с потоками. Например, у класса Thread есть статическое
    Глава свойство CurrentThread. Значением этого свойства является ссылка на объект потока, в котором запрашивается свойство НАЗ А МЕТКУ Например, мы имели дело с главным потоком, но никогда ранее не упоминали объект главного потока. Меж тем он существует, и к нему можно получить доступ. Для этого в главном потоке следует воспользоваться свойством
    CurrentThread класса У объекта потока есть свойство Name, определяющее название потока. Свойство Priority объекта потока определяет приоритет потока. Возможные значения свойства — константы Highest, AboveNormal,
    Normal
    (значение по умолчанию, BelowNormal и Lowest из перечисления НАЗ А МЕТКУ Приоритет потока влияет на доступ потока к системным ресурсам, особенно если несколько потоков конкурируют за один и тот же ресурс. Обычно определяющим является не само значение приоритета, а то, у какого из потоков приоритет выше.
    С помощью метода Abort() можно завершить выполнение потока, из объекта которого вызывается метод. Небольшой пример, в котором используются перечисленные выше свойства, представлен в листинге Листинг 6.6. Операции с потоками System;
    using System.Threading;
    //
    Ƚɥɚɜɧɵɣ ɤɥɚɫɫ:
    class CurrentThreadDemo{
    //
    ɋɬɚɬɢɱɟɫɤɨɟ ɩɨɥɟ:
    static int state=0;
    //
    ɋɬɚɬɢɱɟɫɤɢɣ ɦɟɬɨɞ:
    static void run(bool type){
    //
    ɋɫɵɥɤɚ ɧɚ ɨɛɴɟɤɬ ɩɨɬɨɤɚ,
    //
    ɜ ɤɨɬɨɪɨɦ ɜɵɡɵɜɚɟɬɫɹ ɦɟɬɨɞ:

    Многопоточное программирование Thread t=Thread.CurrentThread;
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɫɨɨɛɳɟɧɢɹ ɫ ɧɚɡɜɚɧɢɟɦ ɩɨɬɨɤɚ:
    Console.WriteLine(
    Ǝɉɨɬɨɤ Ǝ+t.Name+Ǝ ɡɚɩɭɳɟɧ...Ǝ);
    //
    Ȼɟɫɤɨɧɟɱɧɵɣ ɰɢɤɥ:
    while(true){
    //
    ɂɡɦɟɧɟɧɢɟ ɡɧɚɱɟɧɢɹ ɫɬɚɬɢɱɟɫɤɨɝɨ ɩɨɥɹ:
    if(type) state++;
    else state--;
    //
    ɉɨɬɨɤ ɩɪɢɨɫɬɚɧɚɜɥɢɜɚɟɬ ɜɵɩɨɥɧɟɧɢɟ:
    Thread.Sleep(1000);
    }
    }
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:
    static void Main(){
    //
    ɉɨɥɭɱɟɧɢɟ ɫɫɵɥɤɢ ɧɚ ɝɥɚɜɧɵɣ ɩɨɬɨɤ:
    Thread t=Thread.CurrentThread;
    //
    ɇɚɡɜɚɧɢɟ ɩɨɬɨɤɚ:
    t.Name=
    ƎBaseƎ;
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɫɨɨɛɳɟɧɢɹ ɫ ɧɚɡɜɚɧɢɟɦ ɩɨɬɨɤɚ:
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ {0} ɡɚɩɭɳɟɧ...Ǝ,t.Name);
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɡɧɚɱɟɧɢɹ ɫɬɚɬɢɱɟɫɤɨɝɨ ɩɨɥɹ:
    Console.WriteLine(
    Ǝɇɚɱɚɥɶɧɨɟ ɡɧɚɱɟɧɢɟ: {0}Ǝ,state);
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɞɥɹ ɩɟɪɜɨɝɨ ɞɨɱɟɪɧɟɝɨ ɩɨɬɨɤɚ:
    Thread up=new Thread(()=>run(true));
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɞɥɹ ɜɬɨɪɨɝɨ ɞɨɱɟɪɧɟɝɨ ɩɨɬɨɤɚ:
    Thread down=new Thread(()=>run(false));
    //
    ɇɚɡɜɚɧɢɟ ɞɥɹ ɩɟɪɜɨɝɨ ɩɨɬɨɤɚ:
    up.Name=
    ƎAlphaƎ;
    //
    ɉɪɢɨɪɢɬɟɬ ɞɥɹ ɩɟɪɜɨɝɨ ɩɨɬɨɤɚ:
    up.Priority=ThreadPriority.Highest;
    //
    ɇɚɡɜɚɧɢɟ ɞɥɹ ɜɬɨɪɨɝɨ ɩɨɬɨɤɚ:
    down.Name=
    ƎBravoƎ;
    Глава 6
    300
    //
    ɉɪɢɨɪɢɬɟɬ ɞɥɹ ɜɬɨɪɨɝɨ ɩɨɬɨɤɚ:
    down.Priority=ThreadPriority.Lowest;
    //
    Ɂɚɩɭɫɤ ɩɟɪɜɨɝɨ ɩɨɬɨɤɚ:
    up.Start();
    //
    Ɂɚɩɭɫɤ ɜɬɨɪɨɝɨ ɩɨɬɨɤɚ:
    down.Start();
    //
    ɉɪɢɨɫɬɚɧɨɜɥɟɧɨ ɜɵɩɨɥɧɟɧɢɟ ɝɥɚɜɧɨɝɨ ɩɨɬɨɤɚ:
    Thread.Sleep(5000);
    //
    Ɂɚɜɟɪɲɟɧɢɟ ɜɵɩɨɥɧɟɧɢɹ ɩɟɪɜɨɝɨ ɩɨɬɨɤɚ:
    up.Abort();
    //
    Ɂɚɜɟɪɲɟɧɢɟ ɜɵɩɨɥɧɟɧɢɹ ɜɬɨɪɨɝɨ ɩɨɬɨɤɚ:
    down.Abort();
    //
    ɂɬɨɝɨɜɨɟ ɡɧɚɱɟɧɢɟ ɫɬɚɬɢɱɟɫɤɨɝɨ ɩɨɥɹ:
    Console.WriteLine(
    Ǝɂɬɨɝɨɜɨɟ ɡɧɚɱɟɧɢɟ: {0}Ǝ,state);
    //
    ɋɨɨɛɳɟɧɢɟ ɨ ɡɚɜɟɪɲɟɧɢɢ ɝɥɚɜɧɨɝɨ ɩɨɬɨɤɚ:
    Console.WriteLine(
    ƎȽɥɚɜɧɵɣ ɩɨɬɨɤ {0} ɡɚɜɟɪɲɟɧ...Ǝ,t.Name);
    Результат выполнения программы может быть таким:
    
    1   ...   19   20   21   22   23   24   25   26   ...   40


    написать администратору сайта