GetMessage с таймаутом

У меня есть приложение, которое вызывает второй потокGetMessage() в цикле. В какой-то момент первый поток понимает, что пользователь хочет выйти из приложения, и уведомляет второй поток о том, что оно должно завершиться. Как второй поток застрял наGetMessage(), программа никогда не выходит. Есть ли способ ждать сообщения с таймаутом? Я тоже открыт для других идей.

РЕДАКТИРОВАТЬ (дополнительные пояснения)

Второй поток запускает этот фрагмент кода:

while ( !m_quit && GetMessage( &msg, NULL, 0, 0 ) )
{
    TranslateMessage( &msg );
    DispatchMessage( &msg );
}

Первая нить устанавливаетm_quit верно.

Ответы на вопрос(5)

PeekMessage() вместо. Но я думаю, что это не будет полным решением проблем.

MsgWaitForMultipleObjects без какого-либо объекта.

MsgWaitForMultipleObjects(0, NULL, FALSE, timeout, QS_ALLEVENTS);

Если, если возвращаетсяWAIT_TIMEOUT это тайм-аут, но если он вернетсяWAIT_OBJECT_0 ты можешь позвонитьGetMessage с гарантией не будет заблокирован.

Но обратите внимание на следующее:

MsgWaitForMultipleObjects does not return if there is unread input of the specified type in the message queue after the thread has called a function to check the queue.

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

Вероятно, ваш лучший вариант будет заменитьGetMessage с:

if (MsgWaitForMultipleObjects(0, NULL, FALSE, timeout, QS_ALLEVENTS) == WAIT_OBJECT_0)
{
    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
    {
        //dispatch the message
    }
}

Но, как я уже говорил, я не тестировал его, поэтому не уверен, сработает ли он.

которую вы всегда можете сделать, это просто отправить заблокированному потоку определенное пользователем сообщение, которое заставит его проснуться, обработать сообщение, а затем вернуться обратно к началу цикла. На самом деле, было бы проще всего полностью удалитьm_quit переменная и вместо этого просто отправить основному потоку сообщение, в котором говорится, что "вам нужно выйти сейчас."

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

UINT_PTR timerId=SetTimer(NULL, NULL, 1000, NULL) перед звонкомGetMessage, Это опубликуетWM_TIMER сообщение в вызывающий поток каждую секунду, поэтомуGetMessage вернется быстро. Затем позвонитеKillTimer(NULL, timerId) отменить это.

UPDATE Образец кода:

BOOL GetMessageWithTimeout(MSG *msg, UINT to)
{
    BOOL res;
    UINT_PTR timerId = SetTimer(NULL, NULL, to, NULL);
    res = GetMessage(msg);
    KillTimer(NULL, timerId);
    if (!res)
        return FALSE;
    if (msg->message == WM_TIMER && msg->hwnd == NULL && msg->wParam == timerId)
        return FALSE; //TIMEOUT! You could call SetLastError() or something...
    return TRUE;
}

сPostThreadMessage.

Например.

PostThreadMessage(threadid, WM_QUIT, 0, 0);

Вам не нужно читатьm_quit переменная во втором потоке, но вы должны проверить на наличие ошибокGetMessage а также возвращаемое значениеFALSE/0 это то, что возвращается, если следующее сообщение является сообщением о выходе.

ВАШ ОТВЕТ НА ВОПРОС