Сначала позвольте мне сказать, что я примерно искал stackoverflow для этого, но не смог найти конкретный ответ.
Мой вопрос довольно теоретический, и нет проблем с запуском любого кода. Пожалуйста, рассмотрите простое приложение MFC с событием таймера и кнопкой (прикрепленной к событию OnClick).
void SampleDlg::OnTimer(UINT_PTR nIDEvent)
{
CString msg;
msg.Format("time: %lld, tid: %d", (int64_t)time(0), GetCurrentThreadId());
SetWindowText(msg);
}
Интуиция подсказывает, что если я сплю внутри события OnClick, основной поток пользовательского интерфейса должен зависнуть, а события таймера не должны срабатывать.
void SampleDlg::OnClick()
{
Sleep(10000);
}
Это нормально, однако, если я показываю новый модальный диалог внутри OnClick, события таймера все равно происходят. Что здесь отличается?
void SampleDlg::OnClick()
{
CString msg;
msg.Format("tid: %d is waiting...", GetCurrentThreadId());
::MessageBox(GetSafeHwnd(), msg, "Msg", 0);
// at this point msgbox tells us that thread with tid is waiting
// thread with tid wont reach this line until msgbox is closed
}
Редактировать: Я включил GetCurrentThreadId()
звонки, чтобы сделать то, что я хочу спросить более ясно.
Когда я запускаю приведенный выше код, msgbox и заголовок окна дают мне один и тот же идентификатор потока: 22012 (например). Мой вопрос, каково значение PC / IP (счетчик программы или указатель команд) потока 22012, когда отображается msgbox?
MessageBox имеет свой собственный цикл сообщений, как и все модальные диалоги.
Поэтому он использует PeekMessage / GetMessage. Сообщения WM_TIMER и WM_PAINT являются псевдо-сообщениями, которые генерируются при выполнении цикла сообщений.
Это означает, что MessageBox внутренне вызывает GetMessage или PeekMessage, и это приводит к тому, что поток все еще выполняет MessageBox, но новые сообщения доставляются в ваши окна.