На этом шаге мы рассмотрим эти операции и приведем пример их использования.
Существуют свойства и методы, которые позволяют выполнять различные операции с потоками. Например, у класса Thread есть статическое свойство CurrentThread. Значением этого свойства является ссылка на объект потока, в котором запрашивается свойство.
 
Например, мы имели дело с главным потоком, но никогда ранее не упоминали объект главного потока. Меж тем он существует, и к нему можно получить доступ. Для этого в главном потоке следует 
воспользоваться свойством CurrentThread класса Thread.
У объекта потока есть свойство 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;
 
В методе run() была аналогичная команда. Но, во-первых, переменная t в методе run() и переменная t в главном методе - это совершенно разные переменные. 
Во-вторых, значением инструкции Thread.CurrentThread является ссылка на объект потока, в котором эта инструкция выполняется. Поэтому в методе run() в переменную t 
записывается ссылка на объект потока, в котором выполняется метод run(), а в главном методе в переменную t записывается ссылка на объект главного потока.
Командой
  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();
 
Напомним, что метод run() содержит бесконечный цикл, а созданные потоки не являются фоновыми, поэтому они должны были бы выполняться бесконечно долго.
После завершения работы дочерних потоков проверяется значение поля state. От запуска к запуску это значение может меняться, но обычно оно не сильно отличается от начального значения 0 (поскольку каждый из дочерних потоков успевает выполнить примерно одинаковое количество циклов по изменению значения поля). Завершается выполнение главного потока отображением сообщения соответствующего содержания.
На следующем шаге мы рассмотрим синхронизацию потоков.