Одним из ключевых аспектов в современном программировании является многопоточность. Ключевым понятием при работе с многоопоточностью является поток. Поток предствляет некоторую часть кода программы. При выполнении программы каждому потоку выделяется определенный квант времени. И при помощи многопоточности мы можем выделить в приложении несколько потоков, которые будут выполнять различные задачи одновременно. Если у нас, допустим, графическое приложение, которое посылает запрос к какому-нибудь серверу или считывает и обрабатывает огромный файл, то без многопоточности у нас бы блокировался графический интерфейс на время выполнения задачи. А благодаря потокам мы можем выделить отправку запроса или любую другую задачу, которая может долго обрабатываться, в отдельный поток. Поэтому, к примеру, клиент-серверные приложения (и не только они) практически не мыслимы без многопоточности.
Основной функционал для использования потоков в приложении сосредоточен в пространстве имен System.Threading. В нем определен класс, представляющий отдельный поток - класс Thread.
Класс Thread определяет ряд методов и свойств, которые позволяют управлять потоком и получать информацию о нем. Основные свойства класса:
ExecutionContext: позволяет получить контекст, в котором выполняется поток
IsAlive: указывает, работает ли поток в текущий момент
IsBackground: указывает, является ли поток фоновым
Name: содержит имя потока
ManagedThreadId: возвращает числовой идентификатор текущего потока
Priority: хранит приоритет потока - значение перечисления ThreadPriority:
Lowest
BelowNormal
Normal
AboveNormal
Highest
По умолчанию потоку задается значение Normal. Однако мы можем изменить приоритет в процессе работы программы. Например, повысить важность потока, установив приоритет Highest. Среда CLR будет считывать и анализировать значения приоритета и на их основании выделять данному потоку то или иное количество времени.
ThreadState возвращает состояние потока - одно из значений перечисления ThreadState:
Aborted: поток остановлен, но пока еще окончательно не завершен
AbortRequested: для потока вызван метод Abort, но остановка потока еще не произошла
Background: поток выполняется в фоновом режиме
Running: поток запущен и работает (не приостановлен)
Stopped: поток завершен
StopRequested: поток получил запрос на остановку
Suspended: поток приостановлен
SuspendRequested: поток получил запрос на приостановку
Unstarted: поток еще не был запущен
WaitSleepJoin: поток заблокирован в результате действия методов Sleep или Join
В процессе работы потока его статус многократно может измениться под действием методов. Так, в самом начале еще до применения метода
Start его статус имеет значение Unstarted
. Запустив поток, мы изменим его статус на Running
.
Вызвав метод Sleep, статус изменится на WaitSleepJoin
.
Кроме того статическое свойство CurrentThread класса Thread позволяет получить текущий поток
В программе на C# есть как минимум один поток - главный поток, в котором выполняется метод Main.
Например, используем вышеописанные свойства для получения информации о потоке:
using System.Threading; // получаем текущий поток Thread currentThread = Thread.CurrentThread; //получаем имя потока Console.WriteLine($"Имя потока: {currentThread.Name}"); currentThread.Name = "Метод Main"; Console.WriteLine($"Имя потока: {currentThread.Name}"); Console.WriteLine($"Запущен ли поток: {currentThread.IsAlive}"); Console.WriteLine($"Id потока: {currentThread.ManagedThreadId}"); Console.WriteLine($"Приоритет потока: {currentThread.Priority}"); Console.WriteLine($"Статус потока: {currentThread.ThreadState}");
В этом случае мы получим примерно следующий вывод:
Имя потока: Имя потока: Метод Main Запущен ли поток: True Id потока: 1 Приоритет потока: Normal Статус потока: Running
Так как по умолчанию свойство Name у объектов Thread не установлено, то в первом случае мы получаем в качестве значения этого свойства пустую строку.
Также класс Thread определяет ряд методов для управления потоком. Основные из них:
Статический метод GetDomain возвращает ссылку на домен приложения
Статический метод GetDomainID возвращает id домена приложения, в котором выполняется текущий поток
Статический метод Sleep останавливает поток на определенное количество миллисекунд
Метод Interrupt прерывает поток, который находится в состоянии WaitSleepJoin
Метод Join блокирует выполнение вызвавшего его потока до тех пор, пока не завершится поток, для которого был вызван данный метод
Метод Start запускает поток
Например, применим метод Sleep для задания задержки выполнения приложения:
using System.Threading; for(int i = 0; i < 10; i++) { Thread.Sleep(500); // задержка выполнения на 500 миллисекунд Console.WriteLine(i); }