Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Что в действительности делает CEvent::SetEvent?


Автор: Dims 2.12.2009, 17:44
В мануале написано, что CEvent::SetEvent()

Sets the state of the event to signaled, releasing any waiting threads.

Но как это может быть правдой, если, например, событие ручное и управляется вот таким кодом:

Код

CSingleLock lock( &event_object, TRUE );
event_object.SetEvent();
lock.Unlock();


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

Что я понимаю не так?

Автор: NiJazz 2.12.2009, 23:06
Ожидающие потоки ждут возбуждения события - типа команды "старт". Это происходит при вызове SetEvent. Документация не врёт smile

Автор: Dims 3.12.2009, 18:55
Но ждут-то они возможности залочить этот объект! Если они смогут это сделать до того, как данный поток отпустит его, то получится, что объект захвачен двумя потоками сразу, а это невозможно!

Автор: NiJazz 5.12.2009, 01:12
Вам точно нужны события, а не мьютекс? Мьютекс как раз обладает семантикой владения, в отличие от событий. Событие - это вкл/выкл, на него может реагировать сколь угодное количество потоков, а мьютекс захватывается лишь одним (кому повезло). 

Захват мьютекса - WaitForSingleObject при возврате.
Освобождение - ReleaseMutex.

Автор: Dims 7.12.2009, 21:36
Я думаю, мне нужно именно событие, так как у меня один поток должен "дать пинка" другому.  

Но интересно, как с ним работать не на Win32, а на MFC. Я не подумал, что может быть объект, у которого нет семантики захватывания.

Но в случае MFC я должен пользоваться классом CSingleLock, а его имя говорит именно о захватывании.

Так что же, код правильный, просто никакого захватывания не происходит?

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

Автор: Earnest 8.12.2009, 12:54
CSingleLock использовать с событиями как-то действительно не логично. Как уже писали, нет там семантики захвата. И в чем проблема? С одной стороны делаешь SetEvent, а с другой - ждешь WaitForSingleObject. Но лучше не Single, конечно. Я обычно потоки синхронизирую так: есть простенькая оболочка для функции потока, для каждого потока создается свой StopEvent (чтобы красиво тормознуть, если надо), и любое колическтво событий-пинков (или не событий - это могут быть любые объекты синхронизации, кроме CS). Для каждого объекта (они храняться как массив хандлов) устанавливается свой обработчик. В результате функция потока представляет собой цикл ожидания всех этих объектов. Если пришел StopEvent, функция завершается, если что-то другое - выполняется соответствующий обработчик.
Цитата(Dims @  7.12.2009,  22:36 Найти цитируемый пост)
Более подробно, мне нужно сделать синхронный вызов функции в другом потоке, то есть, вызывающий поток должен инициировать работу функции в другом потоке, а сам подождать окончания её работы.  

Здесь нужны два события, доступные обоим потокам: первый поток готовит данные, устанавлоивает событие Start и начинает ждать событие Done. Второй поток ждет событие Start, делает обработку, устанавливает Done. И, кстати, оба  с автосбросом. 
Без автосброса нужно только тогда, когда много потоков пинать нужно.
Одним событием не обойдешься, можно нарваться на то, что первый поток, установив событие и начав его же ждать, первый его и поймает. И чего их экономить, с двумя логика проще и понятнее. 

Автор: Dims 9.12.2009, 19:24
А как сделать WaitFor.. именно на MFC?

Автор: NiJazz 10.12.2009, 00:06
Цитата(Dims @  9.12.2009,  20:24 Найти цитируемый пост)
А как сделать WaitFor.. именно на MFC? 

Код

::WaitForSingleObject( event_object->m_hEvent, INFINITE );

Как-то так.

Автор: Earnest 10.12.2009, 09:46
MFC-шные оболочки WaitForSingleObject / WaitForMultipleObjects - CSingleLock и CMultiLock. Но семантика у них более мутная, чем у апишных Wait... Поэтому даже в коде MFC, особенно для событий, предпочитают пользоваться прямыми апишными функциями. Чего и тебе рекомендую. А вот сами объекты синхронизации (собтыя и прочее) удобнее использовать в оболочках (т.е. не голые хандлы, а CEvent, CMutex и т.д.) - т.к. это избавляет тебя от ручных инициализации и удаления. Если речь идет именно о блокировках (стоять-не двигаться-пока-не отпущу), то вполне удобно использовать CSingleLock\CMultiLock, но как уже сказано, не с событиями.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)