C#中键盘挂钩事件的ShowDialog()
本文关键字:ShowDialog 事件 键盘 | 更新日期: 2023-09-27 17:47:46
我想在触发键盘挂钩事件时调用ShowDialog()
,但我遇到了一些困难:
- ShowDialog()阻塞,所以我不能从钩子触发的事件中调用它,因为它会阻塞操作系统
- 我可以启动一个新线程并从那里调用
ShowDialog()
,但我遇到了一些讨厌的异常。我想我不能在任何其他线程中调用ShowDialog()
- 我可以启动一个计时器:在接下来的50毫秒内调用
ShowDialog()
(这是一个讨厌的BTW黑客攻击,我宁愿不这么做)。但随后计时器在一个新线程中启动,然后我遇到了上一个项目符号中解释的相同问题
有办法吗?
问题可能是您试图将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()不会"阻塞操作系统",所以不要不愿意使用它。