Я провожу большую часть дня, выясняя это (если что-то, что я скажу, неверно, пожалуйста, прокомментируйте и дайте мне знать, чтобы я мог это исправить).Я действительно должен был создать старое приложение Win32 и создать цикл сообщений сам (я довольно постоянный SOB).Таким образом, есть функция WinMain, которая запускает цикл обработки сообщений, который выглядит следующим образом:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Особенность GetMessage () заключается в том, что он блокируется, пока сообщение не станет доступным в очереди сообщений.Если вы запустите Windowed-приложение и просто сидите там и смотрите на окно (не вызывайте никаких действий, которые бы отправили сообщение в очередь), основной поток (поток, в котором было создано окно) приостанавливается на GetMessage (),Теперь, когда сообщение действительно публикуется, мы входим в цикл while (то есть, если сообщение не завершено, что равно 0).DispatchMessage () - интересная функция здесь.Эта функция в конечном итоге приведет к (в .NET) событиям, вызываемым элементами управления и выполнением EventHandlers.Что меня озадачило, если стек вызовов GetMessage () / DispatchMessage () /.../ EventHandler, как это возможно для Application.DoEvents () обрабатывать сообщения?Ну, это довольно просто.DoEvents в Win32 будет выглядеть следующим образом:
void DoEvents()
{
MSG msg;
HACCEL hAccelTable;
hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_TESTWIN32));
// Main message loop:
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0)
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
Таким образом, DoEvents () фактически запускает другой цикл для обработки событий, находясь внутри DispatchMessage () начального цикла сообщения! Ключевым отличием является то, что вместо использования GetMessage (), который блокирует, пока в очереди нет сообщения, мы используем PeekMessage (), который возвращает 0 и существует цикл, когда в очереди больше нет сообщений.
Так что, если мы дважды нажмем кнопку и в EventHandler этой кнопки у нас будет вызов DoEvents ()?Первоначальный цикл обработки событий обработает первый щелчок и вызовет событиеВо время выполнения EventHandler при вызове DoEvents () событие будет запущено второй раз, а EventHandler будет введен снова (что-то вроде рекурсивного вызова).Это страшно!
Итак, в конце концов, все происходит в одном потоке, и DoEvents () фактически блокируется, пока все сообщения не будут обработаны, а затем возвращается.Теперь я пойду спать на пару дней.