1

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

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

有办法吗?

4

6 回答 6

2

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

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

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

于 2008-10-07T01:34:13.550 回答
1

我不确定 ShowDialog,但是当您尝试在后台线程中对 UI 执行某些操作时遇到异常时,这意味着您应该使用 UI 调度程序。

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

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

于 2008-10-07T01:20:38.180 回答
0

没有“讨厌的例外”,很难说出发生了什么。我认为这是因为您的线程不是STA线程,并且 UI 对象在实例化时抛出异常。将新线程的单元模型设置为 STA 而不是MTA,看看是否有帮助。

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

于 2008-10-07T01:22:17.317 回答
0

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

此外,如果您ShowDialog()从另一个线程使用,它将不是模态的(没有父级)。这与使用Show().

于 2008-10-07T01:39:52.820 回答
0

试试这个:

void MyKeyboardHookHandler(...)
{
     WindowsFormsSynchronizationContext.Current.Post(state =>
     {
         Form f = new Form();
         f.ShowDialog();
     }, null);
}
于 2008-10-07T02:54:03.170 回答
-1

ShowDialog() 将阻止您的应用程序的线程,但这是它应该做的。如果您不希望表单阻止您的应用程序,请改为调用 Show()。

ShowDialog() 不会“阻塞操作系统”,所以不要勉强使用它。

于 2008-10-07T01:37:43.370 回答