Поддержка многопоточности осуществляется в.NET в основном с помощью пространства имен System.Threading. Некоторые типы этого пространства описаны в табл. 10.1.
Таблица 10.1. Некоторые типы пространства имен System.Threading
Тип Описание
Interlocked Класс, обеспечивающий синхронизированный доступ к переменным, которые используются в разных потоках
Monitor Класс, обеспечивающий синхронизацию доступа к объектам
Mutex Класс-примитив синхронизации, который используется также для синхронизации между процессами
ReaderWriterLock Класс, определяющий блокировку, поддерживающую один доступ на запись и несколько — на чтение Thread Класс, который создает поток, устанавливает его приоритет, получает информацию о состоянии
ThreadPool Класс, используемый для управления набором взаимосвязанных потоков — пулом потоков
Timer Класс, определяющий механизм вызова заданного метода в заданные интервалы времени для пула потоков
WaitHandle Класс, инкапсулирующий объекты синхронизации, которые ожидают доступа к разделяемым ресурсам
|
|
IOCompletionCallback Класс, получающий сведения о завершившейся операции ввода-вывода
ThreadStart Делегат, представляющий метод, который должен быть выполнен при запуске потока
TimerCallback Делегат, представляющий метод, обрабатывающий вызовы от класса Timer
WaitCallback Делегат, представляющий метод для элементов класса ThreadPool
ThreadPriority Перечисление, описывающее приоритет потока
ThreadState Перечисление, описывающее состояние потока
Первичный поток создается автоматически. Для запуска вторичных потоков используется класс Thread. При создании объекта-потока ему передается делегат, определяющий метод, выполнение которого выделяется в отдельный поток:
Thread t = new Thread (new ThreadStart(имя_метода));
После создания потока заданный метод начинает в нем свою работу, а первичный поток продолжает выполняться. В листинге 10.10 приведен пример одновременной работы двух потоков.
Листинг 10.10. Создание вторичного потока
using System;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static public void Hedgehog() // метод для вторичного потока
{
for (int i = 0; i < 6; ++i)
Console.WriteLine(i); Thread.Sleep(1000);
}
static void Main()
{
Console.WriteLine("Первичный поток " +
Thread.CurrentThread.GetHashCode());
Thread ta = new Thread(new ThreadStart(Hedgehog));
Console.WriteLine("Вторичный поток " + ta.GetHashCode());
ta.Start();
for (int i = 0; i > -6; --1)
{
Console.Write(" " + i); Thread.Sleep(400);
}
}
}
}
Результат работы программы:
Первичный поток 1
Вторичный поток 2
0 0 -1 -2 1 -3 -4 2 -5 3 4 5
В листинге используется метод Sleep, останавливающий функционирование потока на заданное количество миллисекунд. Как видите, оба потока работают одновременно. Если бы они работали с одним и тем же файлом, он был бы испорчен так же, как и приведенный вывод на консоль, поэтому такой способ распараллеливания вычислений имеет смысл только для работы с различными ресурсами. В табл. 10.2 перечислены основные элементы класса Thread.
|
|
Таблица 10.2. Основные элементы класса Thread
Элемент Вид Описание
CurrentThread Статическое Возвращает ссылку на выполняющийся поток (только
свойство для чтения)
IsAlive Свойство Возвращает true или false в зависимости от того,
запущен поток или нет
IsBackground Свойство Возвращает или устанавливает значение, которое
показывает, является ли этот поток фоновым
Name Свойство Установка текстового имени потока
Priority Свойство Получить/установить приоритет потока (используются
значения перечисления ThreadPrority)
ThreadState Свойство Возвращает состояние потока (используются значения
перечисления ThreadState)
Abort Метод Генерирует исключение ThreadAbortException. Вызов
этого метода обычно завершает работу потока
GetData, Статические Возвращает (устанавливает) значение для указанного
SetData методы слота в текущем потоке
GetDomain, Статические Возвращает ссылку на домен приложения
методы (идентификатор домена приложения), в рамках
которого работает поток
GetHashCode Метод Возвращает хеш-код для потока
Sleep Статический Приостанавливает выполнение текущего потока
метод на заданное количество миллисекунд
Interrupt Метод Прерывает работу текущего потока
Join Метод Блокирует вызывающий поток до завершения другого
потока или указанного промежутка времени и
завершает поток
Resume Метод Возобновляет работу после приостановки потока
Start Метод Начинает выполнение потока, определенного делегатом
ThreadStart
Suspend Метод Приостанавливает выполнение потока. Если выполнение
потока уже приостановлено, то игнорируется
Можно создать несколько потоков, которые будут совместно использовать один и тот же код. Пример приведен в листинге 10.11.
Листинг 10.11. Потоки, использующие один объект
using System;
using System.Threading;
namespace ConsoleApplication1
{
class Class1
{
public void Do()
{
for (int i = 0; i < 4; ++i)
{
Console.Write(" " + i);
Thread.SIeep(3);
}
}
class Program
{
static void Main()
{
Class1 a = new Classl();
Thread tl = new Thread(new ThreadStart(a.Do));
tl.Name = "Second";
Console.WriteLine("Поток " + tl.Name);
tl.Start();
Thread t2 = new Thread(new ThreadStart(a.Do));
t2.Name = "Third";
Console.WriteLine("Поток " + t2.Name);
t2.Start();
}
}
}
}
Результат работы программы:
Поток Second
Поток Third
0 0 1 1 2 2 3 3
Варианты вывода могут несколько различаться, поскольку один поток прерывает выполнение другого в неизвестные моменты времени.
Для того чтобы блок кода мог использоваться в каждый момент только одним потоком, применяется оператор lock. Формат оператора: