Работа с потоками в .NET
О чем сегодня поговорим
Основные работы с потоками Средства блокирующей синхронизации Неблокирующая синхронизация Асинхронная модель
программирования Пул потоков Класс BackGroundWorker Задачи Модель поставщик-потребитель Блокировка с двойной проверкой
Определение потока выполнения
Пото�к выполне�ния (англ. thread — нить) — наименьшая единица обработки, исполнение которой может быть назначено ядром операционной системы
Плюсы многопоточного приложения
Параллельная обработка запросов Взаимодействие по сети или с БД Выполнение операций, занимающих
много времени Разделение задач по приоритетам Сохранение возможности работы с UI
при обработке других задач
Недостатки многопоточного приложения
Увеличенный расход памяти Захват времени процессора – если в
одном процессе находится большое количество потоков, то потоки другого процесса срабатывают реже
Контроль доступа к разделяемым ресурсам
Отслеживание времени жизни потока
Отличие потоков от процессов
Процессы - независимы, тогда как потоки выполнения существуют как составные элементы процессов
Процессы несут значительно больше информации о состоянии
Процессы имеют отдельные адресные пространства, тогда как потоки выполнения совместно используют их адресное пространство
Процессы взаимодействуют только через предоставляемые системой механизмы связей между процессами
Переключение контекста между потоками выполнения в одном процессе, как правило, быстрее, чем переключение контекста между процессами.
Класс Thread
Класс Thread
Приоритет потока
Ожидание завершения потока
Фоновые потоки
Обработка исключений в потоках
Перехват необработанных исключений
Останов потока
Thread.InterruptThread.Abort
Thread.Interrupt
Если Interrupt вызывается для неблокированного потока, поток продолжает исполнение до точки следующей блокировки, в которой и генерируется исключениеThreadInterruptedException.
Thread.Abort
• После вызова метода Thread.Abort из другого потока, в целевом потоке генерируется исключение ThreadAbortException, которое по своей природе является асинхронным, а это значит, что оно может возникнуть практически в любой точке управляемого кода
• ThreadAbortException не может возникнуть внутри статического конструктора, внутри блоков catch/finally, внутри constrained execution region или внутри неуправляемого кода.
Thread.Abort
Состояния потока
Когда (не)использовать потоки?
Средства блокирующей синхронизации
Класс Monitor и конструкция lock()
ReaderWriterLockSlimMutexSemaphoreWaitHandle
Класс Monitor
Класс Monitor контролирует доступ к объектам, предоставляя блокировку объекта одному потоку. Блокировки объектов предоставляют возможность ограничения доступа к части кода, обычно называемой критической секцией. Пока поток владеет блокировкой для объекта, никакой другой поток не может ею завладеть.
Класс Monitor
Класс Monitor контролирует доступ к объектам, предоставляя блокировку объекта одному потоку. Блокировки объектов предоставляют возможность ограничения доступа к части кода, обычно называемой критической секцией. Пока поток владеет блокировкой для объекта, никакой другой поток не может ею завладеть.
Double-check locking
Класс ReaderWriterLockSlim
Представляет блокировку, используемую для управления доступом к ресурсу, которая позволяет нескольким потокам производить считывание или получать монопольный доступ на запись.
Mutex
Примитив синхронизации, который также может использоваться в межпроцессорной синхронизации
Semaphore
Ограничивает число потоков, которые могут одновременно получать доступ к ресурсу или пулу ресурсов.
WaitHandle
AutoResetEvent ManualResetEvent
AutoResetEvent Уведомляет ожидающий поток о том, что произошло событие. AutoResetEvent позволяет потокам взаимодействовать друг с
другом путем передачи сигналов. Как правило, этот класс используется, когда потокам требуется исключительный доступ к ресурсу.
Поток ожидает сигнала, вызывая метод WaitOne при возникновении AutoResetEvent. Если AutoResetEvent находится в несигнальном состоянии, поток будет заблокирован, ожидая сигнала потока, в настоящий момент контролирующего ресурс, о том, что ресурс доступен (для этого вызывается метод Set).
Вызов Set сигнализирует событию AutoResetEvent о необходимости освобождения ожидающего потока. Событие AutoResetEventостается в сигнальном состоянии до освобождения одного ожидающего потока, а затем возвращается в несигнальное состояние. Если нет ожидающих потоков, состояние остается сигнальным бесконечно.
Если поток вызывает метод WaitOne, а AutoResetEvent находится в сигнальном состоянии, поток не блокируется. AutoResetEventнемедленно освобождает поток и возвращается в несигнальное состояние.
AutoResetEvent
AutoResetEvent очень похож на турникет – один билет позволяет пройти одному человеку. Приставка “auto” в названии относится к тому факту, что открытый турникет автоматически закрывается или “сбрасывается” после того, как позволяет кому-нибудь пройти. Поток блокируется у турникета вызовом WaitOne (ждать (wait) у данного (one) турникета, пока он не откроется), а билет вставляется вызовом метода Set. Если несколько потоков вызываютWaitOne, за турникетом образуется очередь. Билет может “вставить” любой поток – другими словами, любой (неблокированный) поток, имеющий доступ к объекту AutoResetEvent, может вызвать Set, чтобы пропустить один блокированный поток.
AutoResetEvent Конструктор EventWaitHandle также позволяет создавать
именованные EventWaitHandle, способные действовать через границы процессов. Имя задается обыкновенной строкой и может быть любым. Если задаваемое имя уже используется на компьютере, возвращается ссылка на существующий EventWaitHandle, в противном случае операционная система создает новый. Вот пример:
AutoResetEvent
AutoResetEvent
ManualResetEvent
ManualResetEvent – это разновидность AutoResetEvent. Отличие состоит в том, что он не сбрасывается автоматически, после того как поток проходит через WaitOne, и действует как шлагбаум – Set открывает его, позволяя пройти любому количеству потоков, вызвавших WaitOne. Resetзакрывает шлагбаум, потенциально накапливая очередь ожидающих следующего открытия.
Эту функциональность можно эмулировать при помощи булевой переменной "gateOpen" (объявленной как volatile) в комбинации со "spin-sleeping" – повторением проверок флага и ожидания в течении короткого промежутка времени.
ManualResetEvent может использоваться для сигнализации о завершении какой-либо операции или инициализации потока и готовности к выполнению работы.
Неблокирующая синхронизация
Неблокирующая синхронизация
Асинхронная модель программирования
Асинхронная модель программирования
Пул потоков
Пул потоков
Предоставляет пул потоков, который может использоваться для выполнения задач, отправки рабочих элементов, обработки асинхронного ввода-вывода, ожидания от имени других потоков и обработки таймеров.
Клаcc BackgroundWorker Асинхронное выполнение метода Возможна отмена выполнения Сигнализация хода выполнения
Клаcc BackgroundWorker
Клаcc BackgroundWorker
Клаcc BackgroundWorker
Task и Task<T>
Task и Task<T>
Какие темы не затронули
Класс ParallelPLINQ.NET 4.5 и async
О чем сегодня поговорилиОсновные понятия работы с
потокамиСредства
блокирующей синхронизацииНеблокирующая синхронизацияАсинхронная модель
программированияПул потоковКласс BackGroundWorkerЗадачи
Контакты
Трёшников Павел Ведущий разработчик СМС-ИТ
▪ www.sms-automation.ru
e-mail: [email protected] twitter: @treshnikov