MFC 主 UI 线程工作和模式对话框

MFC main UI thread workings and modal dialogs

首先声明一下,我已经粗略地搜索了Whosebug,但没有找到具体的答案。

我的问题比较理论化,任何代码的 运行ning 都没有问题。请考虑一个带有计时器事件和按钮(附加到 OnClick 事件)的简单 MFC 应用程序。

void SampleDlg::OnTimer(UINT_PTR nIDEvent)
{
    CString msg;
    msg.Format("time: %lld, tid: %d", (int64_t)time(0), GetCurrentThreadId());

    SetWindowText(msg);
}

我的直觉表明,如果我在 OnClick 事件中休眠,主 UI 线程应该挂起,计时器事件不应启动。

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 和 window 标题都给我相同的 thread-id: 22012(例如)。我的问题是,当显示 msgbox 时,线程 22012 的 PC/IP(程序计数器或指令指针)的值是多少?

与所有模态对话框一样,MessageBox 有自己的消息循环。

所以它使用PeekMessage/GetMessage。 WM_TIMER 和 WM_PAINT 消息是消息循环执行时生成的伪消息。

这意味着 MessageBox 在内部调用 GetMessage 或 PeekMessage,这会导致线程仍然执行 MessageBox,但新消息会传递给您 windows。