Страница 1 из 2
Проблема с интерфейсом в многопоточном приложении с событиями
Добавлено: 16 фев 2008, 23:16
engine
В приложении 3 потока. Первый основной, в нем находится оконная процедура обработки сообщений WndProc, создаются два глобальных события (hEvent1 и hEvent2) и два потока (Thread1 и Thread2). Каждому событию hEventx соответствует свой поток Threadx. Структура потоков одинакова и заключается в следующем. В потоке находится бесконечный цикл в котором вызывается ф-ия WaitForSingleObject(hEventx, INFINITE), на которой поток должен остановиться и продолжить свою работу после освобождения события. Освобождения события(SetEvent(hEventx)) происходит в основном потоке в функции WndProc при появлении сообщения о нажатии клавиши Enter на клавиатуре. При нажатии этой клавиши оба события освобождаются и потоки продолжают свою работу. Но проблема в том, что когда потоки переходят в режим ожидания события (натыкаются на WaitForSingleObject), интерфейс окна повисает. И функция WndProc не реагирует на нажатие клавиш. Хотя вызов WaitForSingleObject происходит исключительно в двух созданных потоках.
Примерная структура программы следующая:
Код: Выделить всё
WndProc(...)
{
switch (Message)
{
case WM_CREATE:
{
hEvent1=CreateEvent(NULL,false,false,NULL);
hEvent2=CreateEvent(NULL,false,false,NULL);
_beginthread(Thread1,...);
_beginthread(Thread2,...);
}
break;
case WM_KEYDOWN:
{
SetEven(hEvent1);
SetEven(hEvent2);
}
break;
...
}
}
Thread1(...)
{
...
while(1)
{
WaitForSingleObject(hEvent1, INFINITE);
...
}
...
}
Thread2(...)
{
...
while(1)
{
WaitForSingleObject(hEvent2, INFINITE);
...
}
...
}
Re: Проблема с интерфейсом в многопоточном приложении с событиями
Добавлено: 17 фев 2008, 00:34
WinMain
Поскольку ты выводишь объекты Event из режима ожидания, то циклы
просто "вешают" процессор и он работает только на выполнение этих циклов.
Re: Проблема с интерфейсом в многопоточном приложении с событиями
Добавлено: 17 фев 2008, 01:34
engine
На следующей итерации цикла поток опять входит в режим ожидания на ф-ии: WaitForSingleObject(hEvent1, INFINITE), так как событие hEvent становится занятым автоматически после WaitForSingleObject. Я это указал при создании события, т.е. второй аргумент ф-ии CreateEvent bManualReset=false. Поэтому никаких зацикливаний быть не может.Сколько раз я нажму клавишу, столько и будет итераций циклов.
Re: Проблема с интерфейсом в многопоточном приложении с событиями
Добавлено: 17 фев 2008, 08:58
ssDev
У тебя ошибка гдето в другом месте
Я для интереса запустил этот код и он работает (за исключением SetEven)
Re: Проблема с интерфейсом в многопоточном приложении с событиями
Добавлено: 18 фев 2008, 10:15
Hawk
Не делают ли потоки какой-нить SendMessage основному окну?
Re: Проблема с интерфейсом в многопоточном приложении с событиями
Добавлено: 18 фев 2008, 10:59
Romeo
После
WaitForSingleObject нужно делать вручную прокачку сообщений по той причине, что цикл
while (1) крутится бесконечно и до главного цикла обработки сообщение исполнение не доходит. Вот функция, опробованная веками:
Код: Выделить всё
inline BOOL WaitWithDlgMessageLoop(HWND hDlg, HANDLE hEvent)
{
DWORD dwRet;
MSG msg;
while (1)
{
dwRet = ::MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT);
if (dwRet == WAIT_OBJECT_0)
{
return TRUE; // The event was signaled
}
if (dwRet != WAIT_OBJECT_0 + 1)
{
break; // Something else happened
}
// There is one or more window message available. Dispatch them
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
// check for unicode window so we call the appropriate functions
if (msg.hwnd != NULL && ::IsWindowUnicode(msg.hwnd))
{
if (::GetMessageW(&msg, NULL, 0, 0) > 0)
{
if (!::IsDialogMessageW(hDlg, &msg))
{
::TranslateMessage(&msg);
: :D ispatchMessageW(&msg);
}
}
}
else
{
if (::GetMessageA(&msg, NULL, 0, 0) > 0)
{
if (!::IsDialogMessageA(hDlg, &msg))
{
::TranslateMessage(&msg);
: :D ispatchMessageA(&msg);
}
}
}
if (::WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
{
return TRUE; // Event is now signaled.
}
}
}
return FALSE;
}
Вызывай её вместо цикла while (1).
Re: Проблема с интерфейсом в многопоточном приложении с событиями
Добавлено: 18 фев 2008, 11:28
Hawk
Romeo - то что ты написал актуально если Wait в главном потоке, а у Engine Wait в других потоках, и главный должен прекрасно крутиться пока остальные потоки ждут hEvent в своих Wait-ах. И на цикл обработки сообщений эти потоки никак не влияют. Тут где-то в другом месте проблема. Как я понял Wait-ы почему-то не ждут события а сразу проваливаются.
Re: Проблема с интерфейсом в многопоточном приложении с событиями
Добавлено: 18 фев 2008, 17:37
engine
И я заметил интересное поведение окна диалога:
оказывается интерфейс зависает не сразу после перехода потоков на WaitForSingleObject, а после того как поступит сообщение главной оконной процедуре. Потому что, после перехода потоков на WaitForSingleObject курсор в рич эдите мигает и можно вводить в него слова(но после нажатия Enter они не исчезают, это значит сообщение от рич эдита не обрабатываются оконноц процедурой) и даже выделяются отдельные элементы в лист боксе, но стоит только кликнуть на самом окне диалога вне контролов как все зависает.
Но определенно сказать, что оконная процедура зависает нельзя, она еще принимает сообщения(только не от дочерних окон), даже после того, когда интерфейс не реагирует. Я это выяснил проведя опыт:
Выполнив все действия после которых оба потока перешли в ожидание на ф-ии WaitForSingleObject, я кликнул мышкой на окне диалога и оно зависло. После этого я установил брекпоинт на самое начало оконной процедуры. Затем я накрыл диалоговое окно другим окном(не имеет значения каким) и убрал это окно. По логике нашему приложению должно поступить сообщение о перерисовки диалогового окна. Так и случилось - брекпоинт сработал, значит сообщения от системы поступают и обрабатываются. Но диалоговое окно перерисовывается, только без контролов(простое серое окошко), вот на рисунке часть окна я закрыл другим окном:
http://forum.codenet.ru/attachment.php? ... 1203326491
Можно сделать вывод: обмен сообщениями между главным окном и его дочерними окнами не осуществляется, а обмен сообщениями между системой и главным окном работает нормально.
Re: Проблема с интерфейсом в многопоточном приложении с событиями
Добавлено: 18 фев 2008, 18:21
engine
Re: Проблема с интерфейсом в многопоточном приложении с событиями
Добавлено: 18 фев 2008, 20:31
ssDev
Хмм.....
У тебя передаются сообщения к окну из другого потока. Попробуй убрать вызов Scanf из Thread и я не удевлюсь если у тебя исчезнут зависания