События

События являются самой примитивной разновидностью объектов синхронизации. Они используются для того, чтобы оповестить поток о том, что наступило ожидаемое событие. События – это средства сигнализации объектов для вызова определенных действий. Эти объекты обычно использу­ются для того, чтобы синхронизировать потоки, которые работают по принципу конвейера.

Ответом на событие обычно является возобновление одного или нескольких потоков. Фактически события можно понимать как попытку реализовать функциональность условных переменных без интеграции с мъютексами.

 
 

Схема использования событий достаточно проста (рис.1).

Один из потоков создает объект-событие, вызывая для этого функцию CreateEvent(). При этом событие имеет имя, которое доступно всем потокам активных процессов. В процессе создания или позже этот поток приводит событие к исходному состоянию (отмечено или не отмечено).

Вызывая функцию WaitForSingleObject() или WaitForMultipleObject(), поток может выполнять ожидание момента, когда событие перейдет в отмеченное состояние.

Другой поток, принадлежащий тому же самому или другому процессу, может получить идентификатор события по его имени, например с помощью функции OpenEvent(). Далее, пользуясь функциями SetEvent(), ResetEvent() или PulseEvent(), эта задача может изменить состояние объекта.

Различают два типа событий - с автоматическим (auto reset event) и ручным сбросом (manual reset event), а также два средства их сигнализации - функции PulseEvent() и SetEvent().

Какой-нибудь способ сигнализации можно использовать с разным типом событий. В сочетании это дает четыре варианта действий. Рассмотрим такие действия одну за одной, но сначала остановимся па тому, как создавать события.

Во время выполнения функции SetEvent() происходит сигнализация события. Последующие действия зависят от типа события.

- Для событий с автоматическим сбросом возобновляют выполнение одного потока, который ожидает событие. Если ни один поток событие не ожидает, событие остается в сигнализированном состоянии до тех пор, пока какой-то поток не попробует начать ожидания на этом самом событии. После этого поток немедленно продолжает выполнение, а состояние события автоматически сбрасывается (следующие потоки будут ожидать).

- Для событий с ручным сбросом возобновляются все ожидающие потоки, после чего событие остается в сигнальном состоянии, поэтому все следующие потоки немедленно будут продолжать работу в случае попытки выполнить ожидание. Событие будет оставаться в таком стали до тех пор, пока какой-то поток не сбросит ее вручную, вызвав ResetEvent().

Выполнение функции PulseEvent() подобное до двух последовательных вызовов SetEvent() и ResetEvent(). При этом событие сигнализирует и возобновляет один из потоков, которые ожидают на события (для событий а автоматическим сбросом), или все потоки, что ожидают (для событий с ручным сбросом), затем состояние события сбрасывает. Когда ни одного потока, что ожидает нет, событие немедленно сбрасывает и факт ее сигнализации исчезает.

Вызов функции SetEvent() хранит состояние события, а вызов функции PulseEvent() – нет.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: