Se MessageBox () / related for síncrono, por que o loop de minha mensagem não é congelado?
Por que é que se eu chamo uma função do Windows aparentemente síncrona comoMessageBox()
dentro do meu loop de mensagem, o loop em si não congela como se eu chamasseSleep()
(ou uma função similar) em vez disso? Para ilustrar o meu ponto, pegue o seguinte esqueléticoWndProc
:
int counter = 0;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 1000, NULL); //start a 1 second timer
break;
case WM_PAINT:
// paint/display counter variable onto window
break;
case WM_TIMER: //occurs every second
counter++;
InvalidateRect(hwnd, NULL, TRUE); //force window to repaint itself
break;
case WM_LBUTTONDOWN: //someone clicks the window
MessageBox(hwnd, "", "", 0);
MessageBeep(MB_OK); //play a sound after MessageBox returns
break;
//default ....
}
return 0;
}
No exemplo acima, a função principal do programa é executar um cronômetro e exibir o valor do contador a cada segundo. No entanto, se o usuário clicar em nossa janela, o programa exibirá uma caixa de mensagem e depois emitirá um sinal sonoro depois que a caixa for fechada.
Aqui é onde fica interessante: podemos dizerMessageBox()
é uma função síncrona porqueMessageBeep()
não é executado até que a caixa de mensagem seja fechada. No entanto, o temporizador continua em execução e a janela é repintada a cada segundo, mesmo quando a caixa de mensagem é exibida. Por enquantoMessageBox()
aparentemente é uma chamada de função de bloqueio, outras mensagens (WM_TIMER
/WM_PAINT
) ainda pode ser processado. Tudo bem, exceto se eu substituir o MessageBox por outra chamada de bloqueioSleep()
case WM_LBUTTONDOWN:
Sleep(10000); //wait 10 seconds
MessageBeep(MB_OK);
break;
Isso bloqueia completamente meu aplicativo e nenhum processamento de mensagens ocorre durante os 10 segundos (WM_TIMER
/WM_PAINT
não são processados, o contador não é atualizado, o programa 'congela', etc). Então porque é queMessageBox()
permite que o processamento de mensagens continue enquantoSleep()
não faz? Dado que a minha aplicação é single-threaded, o que é queMessageBox()
faz para permitir essa funcionalidade? O sistema "replica" meu thread de aplicativo, de modo que ele possa concluirWM_LBUTTONDOWN
código uma vezMessageBox()
está feito, enquanto ainda permite que o segmento original para processar outras mensagens no ínterim? (esse foi o meu palpite inculto)
desde já, obrigado