Здравствуйте, Андрей, Вы писали:
А>Здравствуйте, nnnickkk, Вы писали:
N>>Здравствуйте, Аноним, Вы писали:
А>>>>Что-то странно как-то вызывается MsgWaitForMultipleObjects и во втором параметре. А>>>>Туда нужно весь массив передавать, а не только первый элемент. А>>>во первых там не первый элемент указывается а play-ый. Во вторых может ему только один этот ивент и надо ждать. Нету ведь функции MsgWaitForSingleObject
N>>Всё верно. N>>Как я уже писал интересует, то что второе сообщение (play=1) не принимается
А>ты так и не ответил на вопросы отсюда
А>может, ты просто не даешь шанса потоку отработать это событие?
А>такое запросто может быть, если приоритет основного потока выше, чем рабочего А>ты выставил событие и тут же завершил программу или убил поток
Вся эта "непонятка" была специально выделена в тестовый проект.
Сообщения (в данном случае от хука) приходят нечасто, так что говорить что кто-то что-то неуспевает смысла нет.
Приложение также старается дождаться корректного завершения через WaitFor..Object(s) с достаточно большим таймаутом.
Так что эффект, что второй event не срабатыват присутствует (как уже писалось выше только в GUI)
? SD>просто жутко интересно стало в чем же проблема
Сейчас нет возможности. Постараюсь в ближайшие дни закинуть исходники всего подпроекта.
Re: Управление потоком
От:
Аноним
Дата:
23.05.09 02:39
Оценка:
Здравствуйте, nnnickkk, Вы писали:
N>Доброго времи суток
N>Была поставлена задача — управление потоком. То есть, поток запускается, каким-то образом необходимо сообщить ему, чтобы начал работать и после этого чтобы нормально завершился. N>Пришел к следующему — управление через events (HANDLE). N>В качестве примера — код, в котором инициализируется хук перехвата мыши и клавиатуры и в этом же потоке принимаются сообщения от хука. N>Присутствуют HANDLE event[2] — соответственно start/stop. N>Log() — вывод лога, в консоль для CLI и в контролс для GUI.
N>
N>DWORD WINAPI mthread(VOID *lp)
N>{
N> DWORD id = GetCurrentThreadId();
N> MSG msg;
N> BOOL ret;
N> int play = 0;
N> int hook = 0;
N> while(1)
N> {
N> switch (MsgWaitForMultipleObjects(1,&event[play],FALSE,INFINITE,QS_POSTMESSAGE|QS_ALLINPUT))
N> {
N> case WAIT_OBJECT_0:
N> if (!play)
N> {
N> play = 1;
N> hook = SetInputHooks(id,1,1);
N> Log("*-- %ld event - start hook=%d",id,hook);
N> ret = PeekMessage(&msg,NULL,WM_USER,WM_USER+20,PM_NOREMOVE);
N> }
N> else
N> {
N> Log("--* %ld event - exit",id);
N> ResetInputHooks(id);
N> ExitThread(0);
N> }
N> break;
N> case WAIT_OBJECT_0+1:
N> ret = GetMessage(&msg,NULL,WM_USER,WM_USER+100);
N> if (ret)
N> switch (msg.message)
N> {
N> case WM_WORK:
N> Log("-*- %ld WM_WORK",id);
N> break;
N> case WM_HOOK_MOUSE:
N> {
N> short x = LOWORD(msg.lParam);
N> short y = HIWORD(msg.lParam);
N> Log("-*- %ld mouse: %d x=%d y=%d",id,msg.wParam,x,y);
N> }
N> break;
N> case WM_HOOK_KEYBOARD:
N> break;
N> }
N> break;
N> }
N> }
N> return 0L;
N>}
N>
N>Результат: N>CLI — всё ОК. N>GUI — event на завершение потока не "ловится"
N>Дополнительно. N>Предыдущая версия работала на messages (WM_USER+) с тем же эффектом — с какого-то момента принимались или только внешние сообщения или только сообщения от управляющего потока.
N>Всё тестировалось в MinGW, VC6, VC8. Результат один (см. выше).
N>Спасибо.
Нужно в ветке WAIT_OBJECT_0 + 1 заменить GetMessage на цикл с PeekMessage, типа такого
WAIT_OBJECT_0+1:
while PeekMessage(...) do
begin
case Msg.message of
WM_WORK: ...
WM_HOOK_MOUSE: ...
WM_HOOK_KEYBOARD:
end;
end;
А вообще какая-то странная логика. Нафига два звента, если в каждый момент ожидается только один? Нафига стартовать поток до того, как он понадобится, если поток всё равно одноразовый? Вместо стартового эвента можно просто запускать поток. Но даже при такой логике два эвента не нужны, достаточно одного с автосбросом (или самому не забывать сбрасывать) плюс булевый флаг завершения.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, nnnickkk, Вы писали:
N>>Доброго времи суток
N>>Была поставлена задача — управление потоком. То есть, поток запускается, каким-то образом необходимо сообщить ему, чтобы начал работать и после этого чтобы нормально завершился. N>>Пришел к следующему — управление через events (HANDLE). N>>В качестве примера — код, в котором инициализируется хук перехвата мыши и клавиатуры и в этом же потоке принимаются сообщения от хука. N>>Присутствуют HANDLE event[2] — соответственно start/stop. N>>Log() — вывод лога, в консоль для CLI и в контролс для GUI.
N>>
N>>DWORD WINAPI mthread(VOID *lp)
N>>{
N>> DWORD id = GetCurrentThreadId();
N>> MSG msg;
N>> BOOL ret;
N>> int play = 0;
N>> int hook = 0;
N>> while(1)
N>> {
N>> switch (MsgWaitForMultipleObjects(1,&event[play],FALSE,INFINITE,QS_POSTMESSAGE|QS_ALLINPUT))
N>> {
N>> case WAIT_OBJECT_0:
N>> if (!play)
N>> {
N>> play = 1;
N>> hook = SetInputHooks(id,1,1);
N>> Log("*-- %ld event - start hook=%d",id,hook);
N>> ret = PeekMessage(&msg,NULL,WM_USER,WM_USER+20,PM_NOREMOVE);
N>> }
N>> else
N>> {
N>> Log("--* %ld event - exit",id);
N>> ResetInputHooks(id);
N>> ExitThread(0);
N>> }
N>> break;
N>> case WAIT_OBJECT_0+1:
N>> ret = GetMessage(&msg,NULL,WM_USER,WM_USER+100);
N>> if (ret)
N>> switch (msg.message)
N>> {
N>> case WM_WORK:
N>> Log("-*- %ld WM_WORK",id);
N>> break;
N>> case WM_HOOK_MOUSE:
N>> {
N>> short x = LOWORD(msg.lParam);
N>> short y = HIWORD(msg.lParam);
N>> Log("-*- %ld mouse: %d x=%d y=%d",id,msg.wParam,x,y);
N>> }
N>> break;
N>> case WM_HOOK_KEYBOARD:
N>> break;
N>> }
N>> break;
N>> }
N>> }
N>> return 0L;
N>>}
N>>
N>>Результат: N>>CLI — всё ОК. N>>GUI — event на завершение потока не "ловится"
N>>Дополнительно. N>>Предыдущая версия работала на messages (WM_USER+) с тем же эффектом — с какого-то момента принимались или только внешние сообщения или только сообщения от управляющего потока.
N>>Всё тестировалось в MinGW, VC6, VC8. Результат один (см. выше).
N>>Спасибо.
А>Нужно в ветке WAIT_OBJECT_0 + 1 заменить GetMessage на цикл с PeekMessage, типа такого
"Типа такого" дает АНАЛОГИЧНЫЙ результат (опысывалось в предыдущих сообщениях)
А>
А>WAIT_OBJECT_0+1:
А> while PeekMessage(...) do
А> begin
А> case Msg.message of
А> WM_WORK: ...
А> WM_HOOK_MOUSE: ...
А> WM_HOOK_KEYBOARD:
А> end;
А> end;
А>
А>А вообще какая-то странная логика. Нафига два звента, если в каждый момент ожидается только один? Нафига стартовать поток до того, как он понадобится, если поток всё равно одноразовый? Вместо стартового эвента можно просто запускать поток. Но даже при такой логике два эвента не нужны, достаточно одного с автосбросом (или самому не забывать сбрасывать) плюс булевый флаг завершения.
Повторюсь — это тестовый проект большого проекта. Eventы управляют сразу пулом из нескольких потоков, каждый из которых выполняет свою функцию.
Потоки стартуют одновременно, но для предварительной инициализации необходимо время, поэтому предусмотрен механизм синхронного старта — event[0].
Автосброс как раз нафига не нужен, только мешается, т.к. для каждого потока придется выставлять его персонально.
Булевый флаг завершения тоже не прокатит, т.к. функции потоков основываются на ожидании событий/сообщений.
Здравствуйте, Андрей, Вы писали:
А>Здравствуйте, nnnickkk, Вы писали:
N>>Здравствуйте, Аноним, Вы писали:
А>>>>Что-то странно как-то вызывается MsgWaitForMultipleObjects и во втором параметре. А>>>>Туда нужно весь массив передавать, а не только первый элемент. А>>>во первых там не первый элемент указывается а play-ый. Во вторых может ему только один этот ивент и надо ждать. Нету ведь функции MsgWaitForSingleObject
N>>Всё верно. N>>Как я уже писал интересует, то что второе сообщение (play=1) не принимается
А>ты так и не ответил на вопросы отсюда
А>может, ты просто не даешь шанса потоку отработать это событие?
А>такое запросто может быть, если приоритет основного потока выше, чем рабочего А>ты выставил событие и тут же завершил программу или убил поток
Здравствуйте, nnnickkk, Вы писали:
N>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, nnnickkk, Вы писали:
N>>>Доброго времи суток
N>>>Была поставлена задача — управление потоком. То есть, поток запускается, каким-то образом необходимо сообщить ему, чтобы начал работать и после этого чтобы нормально завершился. N>>>Пришел к следующему — управление через events (HANDLE). N>>>В качестве примера — код, в котором инициализируется хук перехвата мыши и клавиатуры и в этом же потоке принимаются сообщения от хука. N>>>Присутствуют HANDLE event[2] — соответственно start/stop. N>>>Log() — вывод лога, в консоль для CLI и в контролс для GUI.
N>>>
N>>>DWORD WINAPI mthread(VOID *lp)
N>>>{
N>>> DWORD id = GetCurrentThreadId();
N>>> MSG msg;
N>>> BOOL ret;
N>>> int play = 0;
N>>> int hook = 0;
N>>> while(1)
N>>> {
N>>> switch (MsgWaitForMultipleObjects(1,&event[play],FALSE,INFINITE,QS_POSTMESSAGE|QS_ALLINPUT))
N>>> {
N>>> case WAIT_OBJECT_0:
N>>> if (!play)
N>>> {
N>>> play = 1;
N>>> hook = SetInputHooks(id,1,1);
N>>> Log("*-- %ld event - start hook=%d",id,hook);
N>>> ret = PeekMessage(&msg,NULL,WM_USER,WM_USER+20,PM_NOREMOVE);
N>>> }
N>>> else
N>>> {
N>>> Log("--* %ld event - exit",id);
N>>> ResetInputHooks(id);
N>>> ExitThread(0);
N>>> }
N>>> break;
N>>> case WAIT_OBJECT_0+1:
N>>> ret = GetMessage(&msg,NULL,WM_USER,WM_USER+100);
N>>> if (ret)
N>>> switch (msg.message)
N>>> {
N>>> case WM_WORK:
N>>> Log("-*- %ld WM_WORK",id);
N>>> break;
N>>> case WM_HOOK_MOUSE:
N>>> {
N>>> short x = LOWORD(msg.lParam);
N>>> short y = HIWORD(msg.lParam);
N>>> Log("-*- %ld mouse: %d x=%d y=%d",id,msg.wParam,x,y);
N>>> }
N>>> break;
N>>> case WM_HOOK_KEYBOARD:
N>>> break;
N>>> }
N>>> break;
N>>> }
N>>> }
N>>> return 0L;
N>>>}
N>>>
N>>>Результат: N>>>CLI — всё ОК. N>>>GUI — event на завершение потока не "ловится"
N>>>Дополнительно. N>>>Предыдущая версия работала на messages (WM_USER+) с тем же эффектом — с какого-то момента принимались или только внешние сообщения или только сообщения от управляющего потока.
N>>>Всё тестировалось в MinGW, VC6, VC8. Результат один (см. выше).
N>>>Спасибо.
А>>Нужно в ветке WAIT_OBJECT_0 + 1 заменить GetMessage на цикл с PeekMessage, типа такого
N>"Типа такого" дает АНАЛОГИЧНЫЙ результат (опысывалось в предыдущих сообщениях)
А>>
А>>WAIT_OBJECT_0+1:
А>> while PeekMessage(...) do
А>> begin
А>> case Msg.message of
А>> WM_WORK: ...
А>> WM_HOOK_MOUSE: ...
А>> WM_HOOK_KEYBOARD:
А>> end;
А>> end;
А>>
А>>А вообще какая-то странная логика. Нафига два звента, если в каждый момент ожидается только один? Нафига стартовать поток до того, как он понадобится, если поток всё равно одноразовый? Вместо стартового эвента можно просто запускать поток. Но даже при такой логике два эвента не нужны, достаточно одного с автосбросом (или самому не забывать сбрасывать) плюс булевый флаг завершения.
N>Повторюсь — это тестовый проект большого проекта. Eventы управляют сразу пулом из нескольких потоков, каждый из которых выполняет свою функцию. N>Потоки стартуют одновременно, но для предварительной инициализации необходимо время, поэтому предусмотрен механизм синхронного старта — event[0]. N>Автосброс как раз нафига не нужен, только мешается, т.к. для каждого потока придется выставлять его персонально. N>Булевый флаг завершения тоже не прокатит, т.к. функции потоков основываются на ожидании событий/сообщений.
Ну и чего? Запустил я Ваш тестовый пример под отладчиком — всё как и ожидалось, сидит, бедолага, в GetMessage. Поменял на PeekMesssage:
case WAIT_OBJECT_0+1:
// ret = GetMessage(&msg,NULL,WM_USER,WM_USER+100);
while (PeekMessage(&msg,NULL,WM_USER,WM_USER+100, PM_REMOVE))
{
// if (ret)
switch (msg.message)
{
case WM_WORK:
Log("-*- %ld WM_WORK",id);
break;
case WM_HOOK_MOUSE:
{
short x = LOWORD(msg.lParam);
short y = HIWORD(msg.lParam);
Log("-*- %ld mouse: %d x=%d y=%d",id,msg.wParam,x,y);
}
break;
case WM_HOOK_KEYBOARD:
break;
}
}
break;
Так что "Типа такого" дает совсем не АНАЛОГИЧНЫЙ результат, и отладчик это показал за одну минуту, блин.
MsgWaitForMultipleObjects срабатывает на добавление события в очередь, поэтому сообщения на каждое такое событие надо вычерпывать до дна, циклом. И именно поэтому GetMessage здесь совершенно неуместна.
Re[14]: Управление потоком
От:
Аноним
Дата:
23.05.09 12:13
Оценка:
Да, забыл дописать после цитаты кода — с изменённым кодом сразу всё заработало. И события мышиные посыпались в IDC_Log, и на команду остановки сразу среагировало. Если там ещё какая функциональность — не проверял, влом. А гонял на VS2005
Здравствуйте, Андрей, Вы писали:
А>Здравствуйте, rastoman, Вы писали:
А>skip
А>хм, автор темы вроде нигде не говорил, что поток подвисает А>хотя в более поздних темах пожалуй признается в зависах
Затык — имеется ввиду что event не приходит, а messages сыпяться исправно.
А>в этом случае надо что-нибудь типа Intel VTune использовать А>он вроде умеет deadlock-и определять
Re[15]: Управление потоком
От:
Аноним
Дата:
25.05.09 13:04
Оценка:
Здравствуйте, nnnickkk, Вы писали:
N>Здравствуйте, Андрей, Вы писали:
А>>Здравствуйте, rastoman, Вы писали:
А>>skip
А>>хм, автор темы вроде нигде не говорил, что поток подвисает А>>хотя в более поздних темах пожалуй признается в зависах N>Затык — имеется ввиду что event не приходит, а messages сыпяться исправно.
С GetMessage при некоторой комбинации действий в окне и мессаги перестают приходить. А вот после исправления