C#中键盘挂钩事件的ShowDialog()

本文关键字:ShowDialog 事件 键盘 | 更新日期: 2023-09-27 17:47:46

我想在触发键盘挂钩事件时调用ShowDialog(),但我遇到了一些困难:

  • ShowDialog()阻塞,所以我不能从钩子触发的事件中调用它,因为它会阻塞操作系统
  • 我可以启动一个新线程并从那里调用ShowDialog(),但我遇到了一些讨厌的异常。我想我不能在任何其他线程中调用ShowDialog()
  • 我可以启动一个计时器:在接下来的50毫秒内调用ShowDialog()(这是一个讨厌的BTW黑客攻击,我宁愿不这么做)。但随后计时器在一个新线程中启动,然后我遇到了上一个项目符号中解释的相同问题

有办法吗?

C#中键盘挂钩事件的ShowDialog()

问题可能是您试图将UI放入非UI线程中。使您的事件从另一个线程激发,并从UI线程调用运行ShowDialog()的方法。

从本质上讲,您希望将UI保留在UI线程上,并将其他任何内容移动到后台线程。

查看Gekki软件了解一些细节(还有无数其他细节——这恰好是我在研究档案中发现的第一个)。

我不确定ShowDialog,但每当您在后台线程中尝试使用UI时出现异常时,这意味着您应该使用UI调度器。

尝试调用使用调用showdialog的委托控制的任何UI对象的BeginInvoke方法(如果您在Windows窗体上)。

此外,请确保尝试(在此之前)在show dialog方法中传递对有效所有者的引用。

试试这个:

void MyKeyboardHookHandler(...)
{
     WindowsFormsSynchronizationContext.Current.Post(state =>
     {
         Form f = new Form();
         f.ShowDialog();
     }, null);
}

您确实应该能够从KeyPress类型的事件中显示对话框。

此外,如果从另一个线程使用ShowDialog(),它将不是模态的(没有父线程)。这将与使用CCD_ 7相同。

如果没有"讨厌的异常",很难判断发生了什么。我认为这是因为你的线程不是STA线程,UI对象在实例化时会抛出异常。将新线程的单元模型设置为STA而不是MTA,看看这是否有帮助。

如果你不知道区别是什么,你应该做一些阅读,例如多线程公寓(MSDN)。

ShowDialog()会阻塞应用程序的线程,但这是它应该做的。如果你不想让窗体阻塞你的应用程序,请调用Show()。

ShowDialog()不会"阻塞操作系统",所以不要不愿意使用它。