【问题标题】:ShowDialog() from keyboard hook event in C#来自 C# 中的键盘挂钩事件的 ShowDialog()
【发布时间】:2008-10-07 01:15:15
【问题描述】:

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

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

有办法吗?

【问题讨论】:

    标签: c# keyboard-hook


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

        试试这个:

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

        【讨论】:

        • 幽灵,这是怎么回事?在后台真正会发生什么?推荐也可以:)
        • 发生的事情是它向您的 WIN32 消息泵发送一条特殊消息。当 WinForms 遇到该消息时,它会执行您在那里传递的函数。它与 someControl.BeginInvoke 相同,但以更可重用的方式(WPF 也使用 SyncContexts!)
        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

          如果你不知道有什么区别,你应该做一些阅读,例如 Multithreaded Apartments (MSDN)。

          【讨论】:

            【解决方案6】:

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

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

            【讨论】:

            • 它将阻止操作系统,因为它位于操作系统范围的键盘挂钩中。
            • 这可能是一个语义问题,但是是吧?整个操作系统都被键盘钩子阻塞了?
            • 抱歉,“操作系统”可能夸大了它。操作系统范围的键盘输入将被阻止。换句话说,您将无法在其他任何地方输入文本。 (还没有测试过这个理论,但我相信这就是会发生的事情。)
            • 我明白你在说什么。当您在 .NET 中使用表单的 ShowDialog 方法以模态方式显示表单时,该表单仅对应用程序而言是模态的,而不是对操作系统而言的。您仍然可以转到其他应用程序并输入。
            • 与 StackOverflow 一样,我不知道为什么我的答案被否决(两次)。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-08-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多