简体   繁体   English

如何在工作线程(非UI线程)中创建模态对话框?

[英]How do I create Modal dialog in worker thread(Non-UI thread)?

I have written a sample MFC application in which there are two threads: -Main thread ( UI thread) -Worker thread ( non-UI thread) 我编写了一个示例MFC应用程序,其中有两个线程: - 主线程(UI线程) - 工作线程(非UI线程)

I have a specific requirement to create a Modal dialog in Non-UI ( worker thread). 我有一个特定的要求,在非UI(工作线程)中创建一个Modal对话框。 When I create the CDialog object and call DoModal on the same, it works. 当我创建CDialog对象并在同一个上调用DoModal时,它可以正常工作。 The dialog gets created and acts as Modal to the application. 该对话框已创建并充当应用程序的模态。 ( Win XP SP2 machine) But this does not work in Windows 2003 server machine. (Win XP SP2机器)但这在Windows 2003服务器机器上不起作用。 The behavior in 2003 server is that, the Modal Dialog goes behind the application main Window and dialog will be brought to front only when I click on Main Window. 2003服务器中的行为是,模态对话框落后于应用程序主窗口,只有当我单击主窗口时,对话框才会显示在前面。 It is not acting as Modal dialog to my application. 它不是我的应用程序的模态对话框。

What could be the problem -- any ideas? 可能是什么问题 - 任何想法?

If creating UI controls in non-UI thread is the issue then is there any Win32 API which will allow me to link my worker thread to Main UI thread such that DoModal happens in Main thread. 如果在非UI线程中创建UI控件是问题,那么是否有任何Win32 API允许我将我的工作线程链接到主UI线程,以便DoModal发生在主线程中。 I tried AttachThreadInput but it is not working. 我尝试了AttachThreadInput,但它无法正常工作。

There is no reliable way to spread GUI modality across multiple threads. 没有可靠的方法在多个线程之间传播GUI模态。 Every window is represented by an object referenced through a HWND which in turn has thread affinity. 每个窗口都由一个HWND引用的对象表示,而该HWND又具有线程关联性。 This is a left-over from the 16-bit days of Windows, where there was no multi threading. 这是Windows的16位天的遗留问题,没有多线程。 Consequently the HWND s are not protected against concurrent access. 因此, HWND不受并发访问保护。 The Old New Thing has an excellent series on "Thread affinity of user interface objects" (Part 1 2 3 Addendum ). Old New Thing有一个关于“用户界面对象的线程亲和性”的优秀系列(第1部分2 3 附录 )。

Modality is implemented by first enabling the dialog window and then disabling its parent. 通过首先启用对话框窗口然后禁用其父窗口来实现模态。 The first step is safe while the second attempts to disable a window from a thread which is not the window's owning thread. 第一步是安全的,而第二步是尝试从不是窗口拥有线程的线程禁用窗口。 Since en-/disabling windows modifies the object referenced through the HWND it represents a race condition. 由于启用/禁用窗口修改通过HWND引用的对象,因此它表示竞争条件。

The suggested solution is to confine your GUI to a single thread and communicate from your worker thread to the GUI thread to have it perform user interaction on the worker thread's behalf. 建议的解决方案是将GUI限制在单个线程中,并从工作线程与GUI线程进行通信,以使其代表工作线程执行用户交互。 The easiest way to accomplish this is to call SendMessage from the worker thread to block until the GUI thread's message handler returns. 完成此操作的最简单方法是从工作线程调用SendMessage来阻止,直到GUI线程的消息处理程序返回。 If the worker thread should continue to run while the dialog is displayed you could use PostMessage instead and communicate back to the worker thread using PostThreadMessage or signaling a synchronization object like an Event Object . 如果在显示对话框时工作线程应继续运行,则可以使用PostMessage,并使用PostThreadMessage与工作线程进行通信,或发信号通知事件对象等同步对象。

First of all, I'd like to agree with other posters that it's probably better to show the dialog on the main UI thread. 首先,我想同意其他海报,在主UI线程上显示对话框可能更好。

However, if you must, you can make a dialog on another thread modal with the following steps: 但是,如果必须,可以使用以下步骤在另一个线程模式上进行对话:

  1. Pass your active window as an owner when creating the dialog. 创建对话框时,将活动窗口作为所有者传递。
  2. When dialog is showing, iterate over your other windows and do them EnableWindow(FALSE) . 显示对话框时,迭代其他窗口并执行EnableWindow(FALSE) When the dialog is hiding, do the reverse. 对话框隐藏时,反过来。 You will probably have to remember windows' enabled state and restore the original state, not just EnableWindow(TRUE) . 您可能必须记住Windows启用状态并恢复原始状态,而不仅仅是EnableWindow(TRUE)
  3. Ensure that accelerators and other global commands will be ignored while the dialog is shown. 确保在显示对话框时忽略加速器和其他全局命令。

Note that (2) shouldn't be necessary provided that you do (1), but you've mentioned MFC, and I don't remember exactly how it behaves. 注意,(2)不应该是必要的,只要你做(1),但你提到了MFC,我不记得它的确切行为。 It has it's own modal dialog implementation which may not exactly match Win32. 它有自己的模态对话框实现,可能与Win32不完全匹配。 If you're lucky, (1) and (3) will be enough. 如果你很幸运,(1)和(3)就足够了。

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

I recommend you not to do what the question subject suggests, and confine all UI to one thread. 我建议你不要做主题建议的问题,并将所有UI限制在一个线程中。 If you need the other thread to communicate with the user, create some messaging mechanism that will ask the UI thread to do it, and transport the results back. 如果您需要其他线程与用户通信,请创建一些消息传递机制,要求UI线程执行此操作,然后将结果传回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM