Is there any way to process all Windows messages while the UI thread is waiting on a WaitHandle or other threading primitive?
当UI线程在WaitHandle或其他线程原语上等待时,有没有办法处理所有Windows消息?
I realize that it could create very messy reentrancy problems; I want to do it anyway.
我意识到它可能会造成非常混乱的重入问题;无论如何我想要这样做。
EDIT: The wait occurs in the middle of a complicated function that must run on the UI thread. Therefore, moving the wait to a background thread is not an option. (Splitting the function in two would make a complicated and unmaintainable mess)
编辑:等待发生在必须在UI线程上运行的复杂函数的中间。因此,将等待移动到后台线程不是一种选择。 (将功能拆分为两个会造成复杂且难以维护的混乱)
4 个解决方案
#1
I'd run the whole "Complicated-function-that-can-not-be-split" in a separate background thread, and have it to report to the GUI only when it needs to (using Invoke/BeginInvoke methods on a control).
我在一个单独的后台线程中运行整个“复杂功能 - 不可分裂”,并让它只在需要时向GUI报告(在控件上使用Invoke / BeginInvoke方法) 。
In a more enhanced version, you should run your complicated function in a non-UI controller that does not depend on the UI, and is easier to unit test. Calling back to the UI and showing the result in the UI, can easily be reached by having the UI to subrscribe to events made available by the controller.
在更强大的版本中,您应该在不依赖于UI的非UI控制器中运行复杂的功能,并且更容易进行单元测试。通过使用UI来描述控制器可用的事件,可以轻松地调用UI并在UI中显示结果。
#2
Why wouldn't you just spawn another thread to do the waiting and have him notify the UI thread via message (or whatever) at the appropriate juncture?
为什么你不会产生另一个线程来做等待并让他在适当的时候通过消息(或其他)通知UI线程?
That's the usual approach to allow for UI thread message handling during a blocking event.
这是在阻塞事件期间允许UI线程消息处理的常用方法。
EDIT: I see now -- you have that app logic logic built into the UI code. Well, this is really a design issue then. You're better off in the long-run breaking that functionality out from the UI into a self-contained object and using some mechanism to communicate status with the UI from your worker.
编辑:我现在看到了 - 你在UI代码中内置了app逻辑逻辑。那么,这真的是一个设计问题。从长远来看,您最好将该功能从UI分解为自包含对象,并使用某种机制与您的工作人员通过UI进行状态通信。
Aside from the benefit of keeping your UI code focused on UI, this allows you to unit-test the logic code separately.
除了将UI代码集中在UI上的好处之外,这还允许您单独对逻辑代码进行单元测试。
#3
Not sure about C#, but in plain Win32 programming, you can use one of the MsgWaitFor...() functions for the actual waiting. It will notify you when messages are present in the message queue, as well as when the object(s) being waited on become signaled. If it reports a message is present, you can call GetMessage(), TranslateMessage(), and DispatchMessage() to process a message, and then go back to waiting.
不确定C#,但在普通的Win32编程中,您可以使用其中一个MsgWaitFor ...()函数进行实际等待。当消息队列中存在消息时,它将通知您,以及等待的对象何时发出信号。如果它报告存在消息,则可以调用GetMessage(),TranslateMessage()和DispatchMessage()来处理消息,然后返回等待。
#4
I'd normally recommend putting your wait condition on another thread.
我通常建议你把等待条件放在另一个线程上。
However, that being said, you can always call Application.DoEvents to process the message pump at any point, including while "waiting" on a wait handle (just timeout, do events, wait with timeout, etc, until you get "through" the waithandle).
然而,话虽如此,你总是可以调用Application.DoEvents来处理消息泵,包括在等待句柄上“等待”(只是超时,做事件,等待超时等等,直到你“通过”等待手段)。
#1
I'd run the whole "Complicated-function-that-can-not-be-split" in a separate background thread, and have it to report to the GUI only when it needs to (using Invoke/BeginInvoke methods on a control).
我在一个单独的后台线程中运行整个“复杂功能 - 不可分裂”,并让它只在需要时向GUI报告(在控件上使用Invoke / BeginInvoke方法) 。
In a more enhanced version, you should run your complicated function in a non-UI controller that does not depend on the UI, and is easier to unit test. Calling back to the UI and showing the result in the UI, can easily be reached by having the UI to subrscribe to events made available by the controller.
在更强大的版本中,您应该在不依赖于UI的非UI控制器中运行复杂的功能,并且更容易进行单元测试。通过使用UI来描述控制器可用的事件,可以轻松地调用UI并在UI中显示结果。
#2
Why wouldn't you just spawn another thread to do the waiting and have him notify the UI thread via message (or whatever) at the appropriate juncture?
为什么你不会产生另一个线程来做等待并让他在适当的时候通过消息(或其他)通知UI线程?
That's the usual approach to allow for UI thread message handling during a blocking event.
这是在阻塞事件期间允许UI线程消息处理的常用方法。
EDIT: I see now -- you have that app logic logic built into the UI code. Well, this is really a design issue then. You're better off in the long-run breaking that functionality out from the UI into a self-contained object and using some mechanism to communicate status with the UI from your worker.
编辑:我现在看到了 - 你在UI代码中内置了app逻辑逻辑。那么,这真的是一个设计问题。从长远来看,您最好将该功能从UI分解为自包含对象,并使用某种机制与您的工作人员通过UI进行状态通信。
Aside from the benefit of keeping your UI code focused on UI, this allows you to unit-test the logic code separately.
除了将UI代码集中在UI上的好处之外,这还允许您单独对逻辑代码进行单元测试。
#3
Not sure about C#, but in plain Win32 programming, you can use one of the MsgWaitFor...() functions for the actual waiting. It will notify you when messages are present in the message queue, as well as when the object(s) being waited on become signaled. If it reports a message is present, you can call GetMessage(), TranslateMessage(), and DispatchMessage() to process a message, and then go back to waiting.
不确定C#,但在普通的Win32编程中,您可以使用其中一个MsgWaitFor ...()函数进行实际等待。当消息队列中存在消息时,它将通知您,以及等待的对象何时发出信号。如果它报告存在消息,则可以调用GetMessage(),TranslateMessage()和DispatchMessage()来处理消息,然后返回等待。
#4
I'd normally recommend putting your wait condition on another thread.
我通常建议你把等待条件放在另一个线程上。
However, that being said, you can always call Application.DoEvents to process the message pump at any point, including while "waiting" on a wait handle (just timeout, do events, wait with timeout, etc, until you get "through" the waithandle).
然而,话虽如此,你总是可以调用Application.DoEvents来处理消息泵,包括在等待句柄上“等待”(只是超时,做事件,等待超时等等,直到你“通过”等待手段)。