Может ли один SetEvent () вызвать несколько WaitForSingleObject () - PullRequest
7 голосов
/ 07 марта 2009

Это:

http://msdn.microsoft.com/en-us/library/ms686915(VS.85).aspx

Казалось бы, нет.

У меня есть три процесса, взаимодействующих через каналы. Процесс A Создает событие, каждый процесс B & C использует WaitForSingleObject (во втором потоке).

Итак, теперь у нас есть -TWO-, каждый из которых ожидает события -SINGLE-.

Процесс A инициирует событие с помощью SetEvent (), Процесс B отвечает, процесс C - нет.

Вывод:

Каждому WaitForSingleObject () требуется уникальное событие ... Правильно?

Ответы [ 4 ]

6 голосов
/ 07 марта 2009

Используйте события ручного сброса для запуска нескольких потоков из одного события.

Здесь - это пример, в котором используется флаг «Событие ручного сброса»

3 голосов
/ 07 марта 2009

Вы можете использовать Вечерний сброс вручную и функцию PulseEvent, чтобы освободить все потоки, в данный момент ожидающие событие.

Заметьте, однако, что этот подход по своей природе является довольно редким, поскольку нет способа определить, какие именно «потоки в настоящее время ожидают ...». Вам следует использовать более надежный механизм синхронизации, если необходимо точное совпадение событий ожидания wakeup / 2.

1 голос
/ 24 февраля 2015

Надеюсь, этот пример поможет вам:

handle1A = CreateEvent(LPSECURITY_ATTRIBUTES, ManualReset, InitialState, NAME)

handle1B = CreateEvent(LPSECURITY_ATTRIBUTES, ManualReset, InitialState, NAME)

handle2A = CreateEvent(LPSECURITY_ATTRIBUTES, ManualReset, InitialState, NAME+GetCurrentThreadId())

handle2B = CreateEvent(LPSECURITY_ATTRIBUTES, ManualReset, InitialState, NAME+GetCurrentThreadId())

A) если вы создаете событие с тем же NAME, каждый setEvent сигнализирует все waitforsingleobjects

SetEvent(handle1A) // Send signaling to handle1A and handle1B

B) если вы создаете событие с уникальным NAME, setEvent отправляет сигнал только на указанный дескриптор

SetEvent(handle2) // Send signling only to handle2A. The Id Thread is unique
0 голосов
/ 11 мая 2017

Одно событие может уведомить несколько потоков, если это событие с ручным сбросом. Событие с автосбросом не может этого сделать. Если более одного протектора ожидает одновременно событие автоматического сброса, и вы установили его в сигнальное состояние, существует только один поток и сбрасывает его, а поведение других потоков будет неопределенным. Хотя из документации Microsoft мы можем предположить, что один и только один поток выйдет, а другие точно не выйдут. В любом случае, мы должны принять во внимание следующую цитату: «Не принимайте заказ« первым пришел - первым вышел »(FIFO). Внешние события, такие как APC в режиме ядра, могут изменить порядок ожидания »Источник - https://msdn.microsoft.com/en-us/library/windows/desktop/ms682655(v=vs.85).aspx

Функция CreateEvent имеет параметр bManualReset. Если это ИСТИНА, функция создает объект события с ручным сбросом, который требует использования функции ResetEvent, чтобы установить состояние события как не сигнализированное. Если этот параметр имеет значение FALSE, функция создает объект события с автоматическим сбросом, и система автоматически сбрасывает состояние события как не сигнализированное после того, как был освобожден единственный ожидающий поток, то есть вышел из функции, такой как WaitForMultipleObjects или WaitForSigleObject, но, как Я писал ранее, только один поток будет уведомлен не все.

Что касается PulseEvent - он ненадежен и никогда не должен использоваться - см. https://msdn.microsoft.com/en-us/library/windows/desktop/ms684914(v=vs.85).aspx

PulseEvent уведомляет только те потоки, которые находятся в состоянии «ожидания» в момент вызова PulseEvent. Если они находятся в каком-либо другом состоянии, они не будут уведомлены, и вы никогда не узнаете наверняка, в каком состоянии находится поток. Поток, ожидающий объекта синхронизации, может быть на мгновение удален из состояния ожидания с помощью асинхронного вызова процедуры в режиме ядра, а затем возвращен в состояние ожидания после завершения APC. Если вызов PulseEvent происходит в то время, когда поток был удален из состояния ожидания, поток не будет освобожден, поскольку PulseEvent освобождает только те потоки, которые ожидают в момент его вызова. Вы можете узнать больше об асинхронных вызовах процедур в режиме ядра (APC) по следующим ссылкам:

Дополнительные сведения о событиях автоматического сброса и событиях ручного сброса можно найти в следующей статье:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...