Warum ist es so, dass, wenn ich eine scheinbar synchrone Windows-Funktion wie MessageBox()
innerhalb meiner Nachrichtenschleife, friert die Schleife selbst nicht ein, als ob ich die Sleep()
(oder eine ähnliche Funktion) zu verwenden? Um meinen Standpunkt zu veranschaulichen, nehmen Sie das folgende Grundgerüst 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;
}
Im obigen Beispiel besteht die Hauptfunktion des Programms darin, einen Timer laufen zu lassen und den Wert des Zählers jede Sekunde anzuzeigen. Wenn der Benutzer jedoch auf unser Fenster klickt, zeigt das Programm ein Meldungsfenster an und piept dann, nachdem das Fenster geschlossen wurde.
Jetzt wird es interessant: Wir können sagen MessageBox()
ist eine synchrone Funktion, weil MessageBeep()
wird erst ausgeführt, wenn das Nachrichtenfeld geschlossen wird. Der Timer läuft jedoch weiter, und das Fenster wird jede Sekunde neu gezeichnet, auch wenn das Meldungsfenster angezeigt wird. Während also MessageBox()
ist offenbar ein blockierender Funktionsaufruf, andere Meldungen ( WM_TIMER
/ WM_PAINT
) können noch bearbeitet werden. Das ist in Ordnung, außer wenn ich MessageBox durch einen anderen blockierenden Aufruf wie Sleep()
case WM_LBUTTONDOWN:
Sleep(10000); //wait 10 seconds
MessageBeep(MB_OK);
break;
Dadurch wird meine Anwendung vollständig blockiert, und während der 10 Sekunden findet keine Nachrichtenverarbeitung statt ( WM_TIMER
/ WM_PAINT
nicht verarbeitet werden, der Zähler nicht aktualisiert wird, das Programm "einfriert", usw.). Wie kommt es also, dass MessageBox()
ermöglicht die Fortsetzung der Nachrichtenverarbeitung, während Sleep()
nicht? Angesichts der Tatsache, dass meine Anwendung single-threaded ist, was ist es, das MessageBox()
um diese Funktionalität zu ermöglichen? Repliziert das System meinen Anwendungs-Thread, so dass es den WM_LBUTTONDOWN
Code einmalig MessageBox()
erledigt ist, während der ursprüngliche Thread in der Zwischenzeit noch andere Nachrichten bearbeiten kann? (das war meine unausgegorene Vermutung)
Vielen Dank im Voraus