【问题标题】:How do I create Modal dialog in worker thread(Non-UI thread)?如何在工作线程(非 UI 线程)中创建模态对话框?
【发布时间】:2010-12-30 10:40:04
【问题描述】:

我编写了一个示例 MFC 应用程序,其中有两个线程: -主线程(UI线程) -Worker线程(非UI线程)

我有在非 UI(工作线程)中创建 Modal 对话框的特定要求。 当我创建 CDialog 对象并在其上调用 DoModal 时,它可以工作。对话框被创建并充当应用程序的模态。 (Win XP SP2 机器)但这在 Windows 2003 服务器机器上不起作用。 2003 服务器中的行为是,模态对话框位于应用程序主窗口的后面,只有当我单击主窗口时,对话框才会被置于前面。它不是我的应用程序的模态对话框。

可能是什么问题——有什么想法吗?

如果在非 UI 线程中创建 UI 控件是问题,那么是否有任何 Win32 API 允许我将我的工作线程链接到主 UI 线程,以便 DoModal 发生在主线程中。我试过AttachThreadInput,但它不起作用。

【问题讨论】:

    标签: c++ windows mfc winapi modal-dialog


    【解决方案1】:

    没有可靠的方法在多个线程间传播 GUI 模式。每个窗口都由一个通过HWND 引用的对象表示,而HWND 又具有线程亲和性。这是 16 位 Windows 时代的遗留物,当时没有多线程。因此,HWNDs 不受并发访问保护。 The Old New Thing有一个优秀的系列“用户界面对象的线程亲和性”(部分123Addendum)。

    模态是通过首先启用对话窗口然后禁用其父窗口来实现的。第一步是安全的,而第二步尝试从不是窗口拥有线程的线程禁用窗口。由于启用/禁用窗口会修改通过 HWND 引用的对象,因此它表示竞争条件。

    建议的解决方案是将您的 GUI 限制在单个线程中,并从您的工作线程与 GUI 线程进行通信,让它代表工作线程执行用户交互。完成此操作的最简单方法是从工作线程调用SendMessage 以阻塞直到GUI 线程的消息处理程序返回。如果在显示对话框时工作线程应该继续运行,您可以改用PostMessage 并使用PostThreadMessage 或向Event Object 之类的同步对象发信号通知工作线程。

    【讨论】:

      【解决方案2】:

      首先,我同意其他发帖者的观点,即在主 UI 线程上显示对话框可能会更好。

      但是,如果必须,您可以通过以下步骤在另一个线程模式上创建一个对话框:

      1. 在创建对话框时将您的活动窗口作为所有者传递。
      2. 显示对话框时,遍历其他窗口并执行它们EnableWindow(FALSE)。当对话框隐藏时,执行相反的操作。您可能必须记住 Windows 的启用状态并恢复原始状态,而不仅仅是 EnableWindow(TRUE)
      3. 确保在显示对话框时忽略加速键和其他全局命令。

      请注意,如果您执行 (1),则 (2) 不是必需的,但您提到了 MFC,我不记得它的具体行为方式。它有自己的模态对话框实现,可能与 Win32 不完全匹配。如果幸运的话,(1)和(3)就足够了。

      【讨论】:

        【解决方案3】:

        我建议您不要按照问题主题的建议去做,并将所有 UI 限制在一个线程中。如果您需要其他线程与用户通信,请创建一些消息传递机制,要求 UI 线程执行此操作,并将结果传输回来。

        【讨论】:

          【解决方案4】:

          虽然我不知道 Server 2003 上对话框处理的细节,但进入主线程的最简单的解决方法是使用自定义窗口消息,执行::SendMessage() 并在消息处理程序中显示对话框。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-05
            相关资源
            最近更新 更多