【问题标题】:Slow button response in WPF appWPF 应用程序中的按钮响应缓慢
【发布时间】:2009-12-11 22:00:15
【问题描述】:

对于我的 WPF 应用程序,我开发了一个虚拟键盘。它在我的开发机器上运行良好。但是,在较慢的机器上,按钮单击响应很慢。单击按钮后,在显示与按钮按下状态和按钮事件更新之前存在延迟。我能做些什么来消除这种延迟?问题是 WPF 显示问题吗?

认为是事件处理程序很慢,我尝试了几种方法来发送键盘按键事件。无论我尝试了什么,交互仍然很慢。目前我正在使用:

SendInput(uint nInputs, ref INPUT pInputs, int cbSize);

从 user32.dll 导入。我的事件处理程序被简化到只为上面的函数创建参数和调用的地步。

我也尝试过使用以下方法,但没有更好的性能:

 System.Windows.Input.Keyboard.FocusedElement.RaiseEvent(...)

我怎样才能摆脱延迟?

【问题讨论】:

  • 您的代码在事件处理程序中做了什么?你能在没有处理程序连接到点击事件的情况下重现问题吗?

标签: c# wpf event-handling button virtual-keyboard


【解决方案1】:

你能说出是什么导致了你的延误吗?

如果您的Click 事件出现缓慢,您可能需要使用单独的Thread 来执行代码。在新线程中,如果您有必须在 UI 线程上执行的代码,请使用 Dispatcher.BeginInvoke 将其排队等待 UI 有处理时间时执行。为了保持 UI 响应,您需要将所有繁重的代码从主 (UI) 线程中移除。

如果您的虚拟键盘位于某个 Window 的本地,则根据您正在执行的操作的复杂性,您可以采用 an approach I've used in the past,您只需手动将键盘字符填充到具有焦点的 TextBox 中。

免责声明:我在 2 年前编写了该代码,因此讨厌它。虽然我通常会假装它不存在,但它可能会帮助你。从那以后我已经做得更好了,但是这个概念本身在速度较慢的机器上没有性能问题。我会引用 Jeff Atwood 的博客关于你最讨厌的代码是你自己的,但是,好吧......

编辑:即使Click 为空,您仍然有问题,您可能需要查看其他潜在的问题。用户的 CPU 是否因某事而达到 100%?要么是太重的动画,要么是另一个潜在的事件?大多数 UI 延迟通常是由于 CPU 用尽或事件在 UI 线程上占用的时间过长造成的。

一种可能性是,如果您的Window 具有AllowsTransparency="True",则大部分工作负载通常会转到显卡will now be rendered in software, and can have heavy performance penalties. 过去,您可以查看Optimizing WPF Application Performance 上的这篇 Microsoft 文章了解一些一般情况可以加快处理速度的提示。

我建议任何使用 XAML 开发的人阅读上一篇文章。诸如使用TextBlockLabel 或实现DependencyPropertyINotifyPropertyChanged 之类的小细节之间的性能差异确实可以加起来,而且他们对每个细节进行基准测试的事实确实表明正确设计的重要性。

【讨论】:

  • 请不要告诉人们使用 Dispatcher.BeginInvoke,就像 DoEvents() 一样!
  • 是的,你是对的,它基本上是一样的,当你已经在线程上时调用 BeginInvoke() 真的没有意义。我已经编辑了我的答案以反映这一点。我认为它不像DoEvents() 那样糟糕,因为您没有强制 UI 线程执行,您只需排队更多代码以在线程上执行,以便让您的 Button 事件可能更快地触发.但即使打出那个解释听起来也很糟糕。
  • 即使 Click 事件处理程序中没有任何内容,响应仍然很慢。
  • 我在回答中添加了更多建议。单独阅读优化 WPF 应用程序性能是一本很好的读物,只是为了确保您以不会影响性能的方式设计 XAML 和类。
【解决方案2】:

刚刚看到这个讨论。我有一个按钮响应很慢的 WinForms 应用程序。这发生在我升级到 64 位 Windows 7 之后。我发现如果我将项目目标更改为“x86”(而不是“Any CPU”),那么缓慢的按钮响应就会消失。

【讨论】:

    【解决方案3】:

    如果您的事件处理程序需要很长时间才能完成,它会在这段时间内锁定 UI。试试这个 事件处理程序:

      private void button1_Click(object sender, RoutedEventArgs e)
      {
         System.Threading.Thread.Sleep(5000);
      }
    

    您的事件处理程序可能只是在更快的机器上完成得更快。对于缓慢的操作,您可能希望将工作推送到另一个线程。

    【讨论】:

    • 我已从事件处理程序中取出所有代码。它将被调用,但不会执行任何操作。按钮响应仍然很延迟。单击按钮后,屏幕会在按钮处于向下状态时更新之前的 3/4 秒。
    猜你喜欢
    • 1970-01-01
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 2014-01-25
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    相关资源
    最近更新 更多