Создание / открытие событий в C ++ и проверка их запуска - PullRequest
1 голос
/ 01 марта 2009

У меня есть два потока, которые используют событие для синхронизации. В каждом потоке они используют один и тот же вызов:

::CreateEvent( NULL,TRUE,FALSE,tcEventName )

Поток-производитель - это тот, кто делает вызов первым, а поток-потребитель делает вызов последним, поэтому он технически открывается, а не создает событие ... Я полагаю.

Но когда SetEvent вызывается в потоке производителя, то же событие никогда не запускается в потоке потребителя (я использую WaitForMultipleObjects ())

Есть ли инструмент, который может сказать мне, действительно ли событие запускается правильно.

Кроме того, когда я вызываю CreateEvent () в каждом потоке, возвращаемое значение дескриптора отличается для каждого ... они должны быть одинаковыми?

Есть ли лучший способ сделать это, чтобы он работал?

Это в Windows XP с использованием Visual Studio 2005

Редактировать: Я сделал еще одну проверку и обнаружил, что при вызове CreateEvent в потоке производителя (второй вызов для CreateEvent) устанавливает LastError равным 183 (ERROR_ALREADY_EXISTS), однако CreateEvent по-прежнему возвращает дескриптор события ... что дает? Как это может быть ошибка, поскольку уже существует, но все еще возвращает дескриптор? Или это должно быть сделано?

Ответы [ 4 ]

1 голос
/ 02 марта 2009

Согласно документации MSDN для CreateEvent ,

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

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

Вы понимаете, что WaitForMultipleObjects () возвращает индекс первого сигнального дескриптора в массиве дескрипторов, верно? Например, если ваше именованное событие является вторым в списке, но первый дескриптор сигнализируется подавляющее большинство времени (например, быстродействующим потоком или событием ручного сброса, которое сигнализируется, но никогда не сбрасывается), WaitForMultipleObjects () всегда возвращает WAIT_OBJECT_0. Другими словами, ваш потребительский поток никогда не увидит тот факт, что ваше именованное событие сигнализируется, потому что первый дескриптор «всегда» сигнализируется. Если это так, поместите ваше именованное событие первым в списке.

Вы случайно не установили параметр bWaitAll для WaitForMultipleObjects () в TRUE, не так ли? Если вы это сделаете, то все дескрипторы в массиве дескрипторов были переданы до того, как функция вернется.

Кто вызывает ResetEvent () для вашего именованного события? Это должен быть потребитель. Это не случайно вызывается каким-то сторонним потоком, не так ли?

Это просто некоторые вещи, которые нужно перепроверить. Если событие все еще не ведет себя так, как вы ожидаете, замените WaitForMultipleObjects () на WaitForSingleObject (), чтобы проверить, правильно ли ваше именованное событие сигнализирует поток потребителя.

Надеюсь, это поможет.

1 голос
/ 01 марта 2009

Если вы просто используете несколько потоков в одном процессе, почему бы вам не передать дескриптор события от одного к другому? Как я знаю, именованные объекты ядра созданы для того, чтобы делиться ими между процессами.

Также вы можете попробовать использовать функцию OpenEvent, чтобы открыть уже созданное событие. Это может дать некоторые идеи.

0 голосов
/ 01 марта 2009

В одном процессе вам нужно всего лишь один раз вызвать CreateEvent и поделиться дескриптором, возвращенным во всех потоках.

Кроме того, вам не нужно называть событие, если вы не хотите, чтобы внешние процессы обращались к событию с помощью OpenEvent. Фактически, если вы назовете событие, только одна копия вашей программы сможет успешно вызвать CreateEvent.

0 голосов
/ 01 марта 2009

Ваш код должен работать так, как вы его описали. Если событие уже существует при попытке его создать, вы получите указатель на существующее событие.

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

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

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