C# - 等待WinForms的消息循环 [英] C# - Waiting for WinForms Message Loop

查看:222
本文介绍了C# - 等待WinForms的消息循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了注册全局热键的C#API。要接收WM_HOTKEY消息,我用的是 System.Windows.Forms.NativeWindow 并运行 System.Windows.Forms.Application一个自己的消息循环。运行(ApplicationContext中)。当用户想注册一个热键,他已经跑 RegisterHotkey()称为一种方法,它停止与 System.Windows.Forms的消息循环。 ApplicationContext.ExitThread(),注册到 RegisterHotKey()(P / Invoke的)功能热键,并重新开始消息循环。这是必需的,因为 RegisterHotKey()必须创建窗口,而这又必须在运行的消息循环相同的线程中实例化的同一个线程中调用。

I have to write an C# API for registering global hotkeys. To receive the WM_HOTKEY message, I use a System.Windows.Forms.NativeWindow and run an own message loop with System.Windows.Forms.Application.Run(ApplicationContext). When the user wants to register a hotkey, he has to run a method called RegisterHotkey() which stops the message loop with System.Windows.Forms.ApplicationContext.ExitThread(), registers the hotkey with the RegisterHotKey() (P/Invoke) function and starts the message loop again. This is required, because RegisterHotKey() must be called within the same thread that created the window, which again must be instantiated within the same thread that runs the message loop.

现在的问题是,如果用户调用启动其运行的消息循环的线程,的ApplicationContext后的 RegisterHotkey()方法很快。了ExitThread()被前称为Application.Run(ApplicationContext中),因此,应用程序无限期地阻塞。是否有人知道一种方法来等待消息循环启动?

The problem is, that if the user calls the RegisterHotkey() method shortly after starting the thread which is running the message loop, ApplicationContext.ExitThread() gets called before Application.Run(ApplicationContext) and therefore the application blocks indefinitely. Does anybody know an approach for waiting for a message loop to be started?

在此先感谢!

推荐答案

所以 RegisterHotKey 需要从创建窗口并开始消息循环相同的线程调用。对 RegisterHotKey 执行为什么不注入到您的自定义消息循环线程?这样,你不需要停止并重新启动消息循环。你可以重复使用第一个你开始,避免了奇怪的比赛条件同时

So RegisterHotKey needs to be called from the same thread that created the window and started the message loop. Why not inject the execution of RegisterHotKey into your custom message loop thread? That way you do not need to stop and restart the message loop. You can just reuse the first one you started and avoid the strange race conditions at the same time.

您可以委派到另一个线程使用注入 ISynchronizeInvoke.Invoke 这将封送代表到托管线程 ISynchronizeInvoke 实例。这是怎么可能做到。

You can inject a delegate onto another thread using ISynchronizeInvoke.Invoke which will marshal that delegate onto the thread hosting the ISynchronizeInvoke instance. Here is how it might be done.

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);
}

我不知道......也许你会想叫 UnregisterHotKey 以及取决于你所追求的行为。我不是那么熟悉这些API,所以我不能对它们如何使用注释。

I do not know...maybe you will want to call UnregisterHotKey as well depending on the behavior you are after. I am not that familiar with these APIs so I cannot comment on how they might be used.

如果您不希望创建,那么你很可能逃脱通过 SendMessage函数表格实例code>等,并处理它 NativeWindow.WndProc 来达到同样的效果,该 ISynchronizeInvoke 方法自动提供。

If you do not want that arbitrary Form instance created then you could probably get away with submitting a custom message to the thread via SendMessage and the like and processing it in NativeWindow.WndProc to get the same effect that the ISynchronizeInvoke methods provide automatically.

这篇关于C# - 等待WinForms的消息循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆