Шаг 239.
Язык программирования C#. Начала.
Многопоточное программирование. Использование потоков (продолжение)

    На этом шаге мы рассмотрим еще одну программу, использующую свойство IsAlive и метод Join().

    Иногда возникает необходимость в одном потоке (например, главном) выполнить определенную команду только после завершения другого потока. В таких случаях используют свойство IsAlive, которое возвращает значение true, если поток (для объекта, из которого запрашивается свойство) еще выполняется. Если поток завершен, значение свойства равно false.

    Вызов метода Join() означает ожидание завершения потока, из объекта которого вызван метод.


Если вызвать метод Join() из объекта потока, который еще не стартовал, генерируется исключение класса ThreadStateException.

    Программа, в которой используются свойство IsAlive и метод Join(), представлена в примере ниже.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Threading;

namespace pr239_1
{
    // Главный класс: 
    class Program
    {
        // Метод для дочернего потока: 
        static void run(){
            Console.WriteLine("Дoчepний поток запущен...");
            // Конструкция цикла: 
            for(int k = 1; k <= 5; k++){
                // Отображение сообщения:
                Console.WriteLine("Дочерний поток: " + k);
                // Задержка в выполнении потока:
                Thread.Sleep(2500);
            }
            Console.WriteLine("Дoчepний поток завершен...");
        }

        // Главный метод: 
        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("Главный поток завершен...");
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    Возможный результат выполнения программы представлен ниже:


Рис.1. Результат работы приложения

    В главном методе программы запускается дочерний поток. В дочернем потоке выполняется статический метод run(). И дочерний, и главный потоки выводят в консольное окно сообщения. Параметры выполнения потоков подобраны таким образом, что главный поток выполняется значительно быстрее. Но в главном потоке размещен условный оператор, в котором проверяется значение свойства IsAlive объекта дочернего потока t. Если условие истинно (то есть если дочерний поток еще выполняется), то выполняется команда t.Join(). Выполнение команды приводит к тому, что главный поток ожидает выполнения дочернего потока, и только после этого в главном потоке выполняется команда

  Console.WriteLine("Главный поток завершен...");   .

    На следующем шаге мы закончим изучение этого вопроса.




Предыдущий шаг Содержание Следующий шаг