Что происходит, когда сообщение запускается до завершения обратного обратного вызова?

Я потратил некоторое время, пытаясь найти окончательный ответ на этот вопрос, и не смог найти надежного источника.

Мой сценарий довольно прост. У меня есть поток с настройкой сообщения сообщений, который обрабатывает повторяющиеся события от таймера. Вот источник сообщения насоса:

// create timer that goes off every 500 ms
UINT_PTR myTimerID = SetTimer(NULL, 0, 500, TimerCallback);

// message structure
MSG msg;

// process and handle messages for this thread
BOOL getMessageStatus;
while((getMessageStatus = GetMessage(&msg, NULL, 0, 0)) != 0)
{
    // failed get message
    if(getMessageStatus == -1)
    {
        printf("GetMessage FAILED!\n");
    }
    // process timer message
    else if(msg.message == WM_TIMER)
    {
        // invoke callback
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

Если TimerCallback занимает более 500 мс, таймер снова запустит событие. Поскольку обратный вызов выполняется в том же потоке, что и насос сообщений, я предполагаю, что обратный вызов должен завершиться до того, как насос сообщений обработает следующее сообщение таймера.

Это верно?

2 ответа

Решение

SetTimer() таймер на основе сообщений Когда таймер истекает, он устанавливает специальный флаг в очереди сообщений. Когда вы качаете очередь для новых сообщений, WM_TIMER сообщение будет создано, если этот флаг был установлен, а другие сообщения с более высоким приоритетом не ожидают в очереди. Пока ваш код занят отправкой сгенерированного WM_TIMER сообщение, таймер может пройти в фоновом режиме и установить флаг снова, генерируя новый WM_TIMER сообщение в следующий раз, когда вы качаете очередь для сообщений. Поэтому будьте осторожны при прокачке сообщений внутри обратного вызова, либо напрямую, либо через модальные диалоговые окна, поскольку это может привести к рекурсивным вызовам обратного вызова таймера и, таким образом, со временем может вызвать переполнение стека. Но если прокачка вашего сообщения происходит только в цикле основного потока, у вас все будет хорошо.

Пока существует только одна точка входа для обработки сообщений, одновременно может обрабатываться только одно сообщение. Вы можете все испортить, обработав больше сообщений в уже запущенном обработчике событий, но просто не делайте этого, и все будет в порядке.

Другие вопросы по тегам