Синхронизация задач с помощью событий

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

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

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

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

На рис. 2 приведен пример использования события для синхронизации двух задач, работающих одновременно. Первая задача занимается отображе­нием данных, которые готовятся второй задачей для отображения.

После создания неотмеченного события первая задача переходит в со­стояние ожидания, пока вторая задача не подготовит для нее данные. Как только это произойдет, вторая задача отмечает и сбрасывает событие, что приводит к завершению ожидания первой задачей. Отобразив подготовлен­ные данные, первая задача опять входит в состояние ожидания, пока вторая задача вновь не подготовит данные и не отметит событие. Таким образом, две задачи синхронизируют свою работу с помощью объекта-события.

 
  синхронизация задач с помощью событий - student2.ru

Для создания события задача должна вызвать функцию CreateEvent, про­тотип которой приведен ниже:

HANDLE CreateEvent(

LPSECURITY_ATRRIBUTES lpEventAttributes, //атрибуты защиты BOOL bManualReset, // флаг ручного сброса события

BOOL bInitialState, // флаг начального состояния события

LPCTSTR lpName); // адрес имени объекта-события.

Параметр IpEventAttributes задает атрибуты защиты и в большинстве слу­чаев может быть указан как NULL.

С помощью параметра bManualReset вы можете выбрать один из двух режимов объекта-события: ручной (TRUE) или автоматический (FALSE).

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

Параметр blnitialState определяет начальное состояние объекта-события; отмеченное (TRUE) или сброшенное (FALSE).

Для того чтобы объектом-событием могли пользоваться задачи, создан­ные разными процессами, необходимо с помощью параметра lpName задать имя события. Имя события подчиняется правилам создания имен языка С. Если событие используется в рамках одного процесса, в качестве имени события можно задать значение NULL. При этом создается безымянное со­бытие.

В случае успешного завершения функция GreateEvent возвращает иден­тификатор события, который можно будет использовать во всех функциях, связанных с событием. При ошибке возвращается NULL. Код ошибки можно получить при помощи функции GetLastError.

Если событие используется с задачами, созданными в рамках одного процесса, его не нужно открывать. Если событие используется для синхрони­зации задач, принадлежащих разным процессам, задача должна открыть со­бытие при помощи функции OpenEvent:

HANDLE OpenEvent(

DWORD fdwAccess, // флаги доступа

BOOL hInherit, // флаг наследования

LPCTSTR IpszEventName); // адрес имени объекта-события

Флаги доступа, передаваемые через параметр fdwAccess, определяют тре­буемый уровень доступа к объекту-событию. Значение EVENT_ALL_ACCESS определяет все возможные флаги доступа. Другие значения флагов подробно описаны в SDK и в данной работе не приводятся.

Параметр hInherit определяет, может ли полученный идентификатор наследоваться дочерними процессами (TRUE) или нет (FALSE).

Через параметр IpszEventName вы должны передать функции адрес символьной строки, содержащей имя открываемого объекта-события.

Функция возвращает идентификатор объекта-события или значение NULL в случае ошибки.

Для установки объекта-события в отмеченное состояние используется функция SetEvent:

BOOL SetEvent(HANDLE hEvent);

В качестве единственного параметра функции необходимо передать идентификатор объекта-события, полученный от функции GreateEvent или OpenEvent.

Сброс события, т.е. установка его в неотмеченное состояние, выполняет­ся функцией ResetEvent:

BOOL ResetEvent(HANDLE hEvent);

Если задача создала событие, работающее в автоматическом режиме, то оно будет сбрасываться и без помощи этой функции, если только какая-либо задача выполняла ожидание этого события и это событие произошло.

Функция PulseEvent выполняет установку объекта-события в отмеченное состояние с последующим сбросом события в неотмеченное состояние:

BOOL PulseEvent(HANDLE hEvent);

Если эта функция вызвана для события, работающего в ручном режиме задачи, выполняющие ожидание этого события, завершат ожидание и продолжает свою работу. Событие при этом будет установлено в неотмеченное

состояние.

Наши рекомендации