Why is it that if I call a seemingly synchronous Windows function like MessageBox()
inside of my message loop, the loop itself doesn't freeze as if I called Sleep()
(or a similar function) instead? To illustrate my point, take the following skeletal WndProc
:
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;
}
In the above example, the program's main function is to run a timer and display the counter's value every second. However, if the user clicks on our window, the program displays a message box and then beeps after the box is closed.
Here's where it gets interesting: we can tell MessageBox()
is a synchronous function because MessageBeep()
doesn't execute until the message box is closed. However, the timer keeps running, and the window is repainted every second even while the message box is displayed. So while MessageBox()
is apparently a blocking function call, other messages (WM_TIMER
/WM_PAINT
) can still be processed. That's fine, except if I substitute MessageBox for another blocking call like Sleep()
case WM_LBUTTONDOWN:
Sleep(10000); //wait 10 seconds
MessageBeep(MB_OK);
break;
This blocks my application entirely, and no message processing occurs for the 10 seconds (WM_TIMER
/WM_PAINT
aren't processed, the counter doesn't update, program 'freezes', etc). So why is it that MessageBox()
allows message processing to continue while Sleep()
doesn't? Given that my application is single-threaded, what is it that MessageBox()
does to allow this functionality? Does the system 'replicate' my application thread, so that way it can finish the WM_LBUTTONDOWN
code once MessageBox()
is done, while still allowing the original thread to process other messages in the interim? (that was my uneducated guess)
Thanks in advance
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…