【问题标题】:MFC main UI thread workings and modal dialogsMFC 主 UI 线程工作和模式对话框
【发布时间】:2015-08-10 01:09:15
【问题描述】:

首先让我说我已经粗略搜索了stackoverflow,但找不到具体答案。

我的问题是理论上的,任何代码的运行都没有问题。请考虑一个带有计时器事件和按钮(附加到 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 和窗口标题都给了我相同的线程 ID:22012(例如)。我的问题是,显示msgbox时线程22012的PC/IP(程序计数器或指令指针)的值是多少?

【问题讨论】:

标签: c++ mfc ui-thread


【解决方案1】:

MessageBox 有它自己的消息循环,就像所有模式对话框一样。

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

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

【讨论】:

  • 是的,我知道其他模式对话框有自己的消息循环。即使他们有自己的 UI 线程(或没有), OnClick() 仍然被阻止,对吧?为什么它不阻塞主对话框的 UI?
  • 没有。他们没有自己的 UI 线程。而且你的主线程没有被阻塞。只要计时器消息和其他消息到达,就不会阻塞任何东西。如果某些 Windows 消息到达调用它,即使您的 onclick 代码也可能会再次执行。
  • 对不起,您能详细说明一下吗?你说“他们没有自己的 UI 线程”和“你的主线程没有被阻塞”。如果它在函数内部等待,它如何不被阻塞?如果它们也使用相同的 UI 线程,其他控件如何不被阻止?
  • 您的线程在等待时总是被阻塞。当一个线程被阻塞时,您总是需要第二个线程来做某事。线程可以执行作业,也可以等待... Y 如果您打开一个消息框或一个新的模式对话框,那么消息循环也会为您的控件泵送消息。如果你想要非阻塞。使用单独的工作线程,让主线程仍然做作业泵送消息。
  • 很抱歉,您在我的评论中没有回答任何问题。我仍然很困惑。 “主线程没有被阻塞”和“他们没有自己的UI线程”怎么会同时发生呢?这些是你写的,对吧?我在主线程中等待,所以它被阻塞了,如果其他对话框没有自己的线程,它们也应该被阻塞。
猜你喜欢
  • 2011-07-03
  • 1970-01-01
  • 2011-07-01
  • 2023-04-06
  • 1970-01-01
  • 2010-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多