Note that there are some explanatory texts on larger screens.

plurals
  1. POIf MessageBox()/related are synchronous, why doesn't my message loop freeze?
    text
    copied!<p>Why is it that if I call a seemingly synchronous Windows function like <code>MessageBox()</code> inside of my message loop, the loop itself doesn't freeze as if I called <code>Sleep()</code> (or a similar function) instead? To illustrate my point, take the following skeletal <code>WndProc</code>:</p> <pre><code>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; } </code></pre> <p>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. </p> <p>Here's where it gets interesting: we can tell <code>MessageBox()</code> is a synchronous function because <code>MessageBeep()</code> 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 <code>MessageBox()</code> is apparently a blocking function call, other messages (<code>WM_TIMER</code>/<code>WM_PAINT</code>) can still be processed. That's fine, except if I substitute MessageBox for another blocking call like <code>Sleep()</code></p> <pre><code> case WM_LBUTTONDOWN: Sleep(10000); //wait 10 seconds MessageBeep(MB_OK); break; </code></pre> <p>This blocks my application entirely, and no message processing occurs for the 10 seconds (<code>WM_TIMER</code>/<code>WM_PAINT</code> aren't processed, the counter doesn't update, program 'freezes', etc). So why is it that <code>MessageBox()</code> allows message processing to continue while <code>Sleep()</code> doesn't? Given that my application is single-threaded, what is it that <code>MessageBox()</code> does to allow this functionality? Does the system 'replicate' my application thread, so that way it can finish the <code>WM_LBUTTONDOWN</code> code once <code>MessageBox()</code> is done, while still allowing the original thread to process other messages in the interim? (that was my uneducated guess)</p> <p>Thanks in advance</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload