На этом шаге мы рассмотрим эти операции и приведем пример их использования.
Существуют свойства и методы, которые позволяют выполнять различные операции с потоками. Например, у класса Thread есть статическое свойство CurrentThread. Значением этого свойства является ссылка на объект потока, в котором запрашивается свойство.
У объекта потока есть свойство Name, определяющее название потока. Свойство Priority объекта потока определяет приоритет потока. Возможные значения свойства - константы Highest, AboveNormal, Normal (значение по умолчанию), BelowNormal и Lowest из перечисления ThreadPriority.
С помощью метода Abort() можно завершить выполнение потока, из объекта которого вызывается метод. Небольшой пример, в котором используются перечисленные выше свойства, представлен в тексте ниже.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace pr242_1 { // Главный класс: class Program { // Статическое поле: 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("Haчaльнoe значение: {0}", state); // Создание объекта для первого дочернего потока: Thread up = new Thread(() => run(true)); // Создание объекта для второго дочернего потока: Thread down = new Thread(() => run(false)); // Название для первого потока: up.Name = "Alpha"; // Приоритет для первого потока: up.Priority = ThreadPriority.Highest; // Название для второго потока: down.Name = "Bravo"; // Приоритет для второго потока: 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. Результат работы приложения
В главном классе объявляется статическое целочисленное поле state с начальным нулевым значением. Еще у нас есть статический метод run() с аргументом логического типа (обозначен как type). В теле метода командой
Thread t = Thread.CurrentThread;
Thread.Sleep(1000); .
В главном методе программы командой
Thread t = Thread.CurrentThread;
Командой
t.Name = "Base";
Thread up = new Thread(() => run(true));
Thread down = new Thread(() => run(false)); .
up.Name = "Alpha";
down.Name = "Bravo";
up.Priority = ThreadPriority.Highest;
down.Priority = ThreadPriority.Lowest;
up.Start();
down.Start(); .
Командой
Thread.Sleep(5000);
up.Abort();
down.Abort();
После завершения работы дочерних потоков проверяется значение поля state. От запуска к запуску это значение может меняться, но обычно оно не сильно отличается от начального значения 0 (поскольку каждый из дочерних потоков успевает выполнить примерно одинаковое количество циклов по изменению значения поля). Завершается выполнение главного потока отображением сообщения соответствующего содержания.
На следующем шаге мы рассмотрим синхронизацию потоков.