Почему, если я вызываю, казалось бы, синхронную функцию Windows, такую как MessageBox()
, внутри моего цикла сообщений, сам цикл не останавливается, как если бы я вызывал Sleep()
(или подобную функцию) вместо этого? Чтобы проиллюстрировать мою точку зрения, возьмите следующий скелет 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;
}
В приведенном выше примере основной функцией программы является запуск таймера и отображение значения счетчика каждую секунду. Однако, если пользователь нажимает на наше окно, программа отображает окно сообщения и затем издает звуковой сигнал после закрытия окна.
Вот где это становится интересным: мы можем сказать, MessageBox()
- синхронная функция, потому что MessageBeep()
не выполняется, пока окно сообщения не будет закрыто. Однако таймер продолжает работать, и окно перекрашивается каждую секунду, даже когда отображается окно сообщения. Таким образом, хотя MessageBox()
, по-видимому, является вызовом функции блокировки, другие сообщения (WM_TIMER
/ WM_PAINT
) все еще могут обрабатываться. Это нормально, за исключением того, что я заменю MessageBox другим блокирующим вызовом, например Sleep()
case WM_LBUTTONDOWN:
Sleep(10000); //wait 10 seconds
MessageBeep(MB_OK);
break;
Это полностью блокирует мое приложение, и в течение 10 секунд не происходит обработки сообщений (WM_TIMER
/ WM_PAINT
не обрабатывается, счетчик не обновляется, программа «зависает» и т. Д.). Так почему же MessageBox()
позволяет продолжить обработку сообщений, а Sleep()
- нет? Учитывая, что мое приложение является однопоточным, что делает MessageBox()
, чтобы разрешить эту функцию? Система «реплицирует» поток моего приложения, чтобы она могла завершить код WM_LBUTTONDOWN
после выполнения MessageBox()
, в то же время позволяя исходному потоку обрабатывать другие сообщения в промежуточный период? (это было мое необразованное предположение)
Заранее спасибо