Jon*_*s W 5 .net c# multithreading message-loop winforms
我必须编写一个C#API来注册全局热键.要接收WM_HOTKEY消息,我使用a System.Windows.Forms.NativeWindow
并运行自己的消息循环System.Windows.Forms.Application.Run(ApplicationContext)
.当用户想要注册一个热键时,他必须运行一个叫RegisterHotkey()
停止消息循环的方法System.Windows.Forms.ApplicationContext.ExitThread()
,将热键注册到RegisterHotKey()
(P/Invoke)函数并再次启动消息循环.这是必需的,因为RegisterHotKey()
必须在创建窗口的同一个线程中调用,该窗口必须在运行消息循环的同一个线程中实例化.
问题是,如果用户RegisterHotkey()
在启动正在运行消息循环的线程后不久调用该方法,则会在ApplicationContext.ExitThread()
之前调用Application.Run(ApplicationContext)
,因此应用程序将无限期地阻塞.有人知道等待消息循环启动的方法吗?
提前致谢!
因此RegisterHotKey
需要从创建窗口的同一线程调用并启动消息循环.为什么不将执行注入RegisterHotKey
到自定义消息循环线程中?这样您就不需要停止并重新启动消息循环.您可以重复使用您开始使用的第一个并同时避免奇怪的竞争条件.
您可以将委托注入另一个线程,使用ISynchronizeInvoke.Invoke
该线程将该委托编组到托管该ISynchronizeInvoke
实例的线程上.这是如何做到的.
void Main()
{
var f = new Form();
// Start your custom message loop here.
new Thread(
() =>
{
var nw = NativeWindow.FromHandle(f.Handle);
Application.Run(new ApplicationContext(f));
}
// This can be called from any thread.
f.Invoke(
(Action)(() =>
{
RegisterHotKey(/*...*/);
}), null);
}
Run Code Online (Sandbox Code Playgroud)
我不知道......也许你会UnregisterHotKey
根据你所追求的行为来打电话.我对这些API并不熟悉,因此我无法评论它们的使用方式.
如果您不希望Form
创建任意实例,那么您可能可以通过SendMessage
等方式向线程提交自定义消息并将其处理NativeWindow.WndProc
以获得与ISynchronizeInvoke
方法自动提供的效果相同的效果.
归档时间: |
|
查看次数: |
3413 次 |
最近记录: |