Windows для профессионалов


Сценарий 3: вызов функций при освобождении отдельных объектов ядра - часть 3


Теперь представьте, что Вы ждете объект ядра "событие с автосбросом": сразу после освобождения он тут же возвращается в занятое состояние; при этом в очередь ста вится соответствующий рабочий элемент. На этом этапе пул продолжает отслеживать объект и снова ждет его освобождения или того момента, когда истечет время, выде ленное на ожидание. Если состояние объекта Вас больше не интересует, Вы должны снять его с регистрации. Это необходимо даже для отработавших объектов, зарегис трированных с флагом WT_EXECUTEONLYONCE. Вот как выглядит требуемая для этого функция:

BOOL UnregisterWaitEx( HANOLE hWaitHandle, HANDLE hCompletionEvent);

Первый параметр указывает на объект ожидания (его описатель возвращается RegisterWaitForSingleObject), а второй определяет, каким образом Вас следует уведом лять о выполнении последнего элемента в очереди. Как и в DeleteTimerQueueTimer, Вы можете передать в этом параметре NULL (если уведомление Вас не интересует), INVA LID_HANULEVALUF, (функция блокируется до завершения обработки всех элементов в очереди) или описатель объекта-события (переходящего в свободное состояние при завершении обработки очередного элемента). В ответ на неблокирующий вызов Unre gisterWaitEx возвращает TRUE, если очередь пуста, и FALSE в ином случае (при этом GetLastError возвращает STATUS_PENDING).

И вновь будьте осторожны, передавая значение INVALIDHANDLE_VALUE. Функция рабочего элемента заблокирует сама себя, если попытается снять с регистрации выз вавший cc объект ожидания. Такая попытка подобна команде: приостановить меня, пока я не закончу выполнение, — полный тупик. Но UnregisterWaitEx разработана так, чтобы предотвращать тупиковые ситуации, когда поток компонента поддержки ожи дания выполняет рабочий элемент, а тот пытается снять с регистрации запустивший его объект ожидания. И еще один момент: не закрывайте описатель объекта ядра до тех пор, пока не снимете его с регистрации. Иначе недействительный описатель по падет в WaitForMultipleObjects, к которой обращается поток компонента поддержки ожидания.Функция моментально завершится с ошибкой, и этот компонент переста нет корректно работать.

И последнее- никогда не вызывайте PulseEvent для освобождения объекта-события, зарегистрированного на ожидание. Поток компонента поддержки ожидания скорее всего будет чем-то занят и пропустит этот импульс от PulseEvent. Но эта проблема для Вас не нова — PulseEvent создает ее почти во всех архитектурах поддержки потоков




Начало  Назад  Вперед



Книжный магазин