Что происходит, когда сообщение запускается до завершения обратного обратного вызова?
Я потратил некоторое время, пытаясь найти окончательный ответ на этот вопрос, и не смог найти надежного источника.
Мой сценарий довольно прост. У меня есть поток с настройкой сообщения сообщений, который обрабатывает повторяющиеся события от таймера. Вот источник сообщения насоса:
// 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
сообщение в следующий раз, когда вы качаете очередь для сообщений. Поэтому будьте осторожны при прокачке сообщений внутри обратного вызова, либо напрямую, либо через модальные диалоговые окна, поскольку это может привести к рекурсивным вызовам обратного вызова таймера и, таким образом, со временем может вызвать переполнение стека. Но если прокачка вашего сообщения происходит только в цикле основного потока, у вас все будет хорошо.
Пока существует только одна точка входа для обработки сообщений, одновременно может обрабатываться только одно сообщение. Вы можете все испортить, обработав больше сообщений в уже запущенном обработчике событий, но просто не делайте этого, и все будет в порядке.