【问题标题】:Why are KeyUp and KeyDown events getting slower?为什么 KeyUp 和 KeyDown 事件变慢?
【发布时间】:2013-04-08 14:21:33
【问题描述】:

我在 WPF 窗口上使用 KeyUp 和 KeyDown 事件。

我在此窗口的 CompositionTarget_Rendering 事件中也有很多调用,用于创建 UIElement 并为其设置动画。这是由下面的引擎类完成的:

int _Fps;
Stopwatch sw = new Stopwatch();

void CompositionTarget_Rendering_Stats(object sender, EventArgs e)
{
    _Fps++;
    var ms = sw.ElapsedMilliseconds;
    sw.Restart();
    engine.Update(ms / 1000f);
    timeFrames.Add(ms);
}

我注意到我拥有的元素越多,获得KeyUp 和KeyDown 事件的速度就越慢。

当我在主窗口中有大约 1000 个 UI 元素时,control_KeyDown 和 control_KeyUp 的代码都会在我按下或释放一个键后大约半秒后执行。

如果 Window 内的动画也很滞后,我不会感到惊讶,但事实并非如此。

  • 帧速率约为 55 fps
  • 动画保持流畅
  • CompositionTarget_Rendering 事件中的计算持续时间不超过 20 毫秒。

似乎只有键盘事件轮询受到重压。

我的问题是:

  • WPF 中键盘处理背后的魔力是什么:为什么它在繁重的情况下会变得迟钝,而不是渲染过程?
  • 如何更好地处理键盘输入并避免这种情况?

编辑:

我写了一个受安迪评论启发的示例。您可以将其复制粘贴到新 WPF 应用程序的主窗口中。它会在按下或按下键时更改窗口的颜色,并在 CompositionTarget_Rendering 事件中填充尽可能多的文本框。

public partial class MainWindow : Window
{
    WrapPanel root2;

    public MainWindow()
    {
        InitializeComponent();
        root2 = new WrapPanel();
        root2.Margin = new Thickness(10);
        this.Content = root2;
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        for (var i = 0; i < 2000; i++)
            root2.Children.Add(new TextBlock() { Background = Brushes.Yellow });

        this.KeyDown += MainWindow_KeyDown;
        this.KeyUp += MainWindow_KeyUp;
        CompositionTarget.Rendering += CompositionTarget_Rendering;
    }

    void MainWindow_KeyUp(object sender, KeyEventArgs e)
    {
        this.Background = Brushes.Red;
    }

    void MainWindow_KeyDown(object sender, KeyEventArgs e)
    {
        this.Background = Brushes.Green;
    }

    void CompositionTarget_Rendering(object sender, EventArgs e)
    {
        foreach (var child in root2.Children)
            ((TextBlock)child).Text = DateTime.Now.Millisecond.ToString();
    }
}

根据您的机器性能,更改 2000 以增加文本框的数量。在一定数量下,CompositionTarget_Rendering 触发器比 KeyUp 或 KeyDown 多。按键时看到边框颜色的变化是相当明显的:按键按下,然后多次触发Composition_Rendering,然后触发keydown事件,边框变为红色。

【问题讨论】:

  • 如果我设置一个新项目,创建一个新表单并添加一个循环来创建 50,000 个文本框并挂钩主窗口 KeyDown 事件,我实际上根本没有注意到任何延迟。这些是嵌套控件吗?
  • 没有嵌套控件。您想尝试在 CompositionTarget_Rendering 事件中放入一些代码,以便在 TextBox 中放入一些随机文本吗?我认为这将反映我所拥有的条件。想了想,50000 个文本框已经很多了。
  • 想知道将文本框放在像 ListBox 这样的虚拟化容器中是否会有所帮助?
  • 不幸的是不是,我认为这与我不知道的事情有关,例如事件中的优先级或其他什么。
  • 在我的机器上,进程的cpu使用率很高,难怪一切都被延迟了。即不是关键事件被延迟,那台机器上的一切都会变慢

标签: wpf keyboard-events


【解决方案1】:

为了回答我的第二个问题,我找到了一种替代方法来执行全局键盘挂钩:Using global keyboard hook (WH_KEYBOARD_LL) in WPF / C#

它的 Keyup 和 Keydown 事件响应没有延迟,事件在 CPU 和图形负载过重。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-24
    • 1970-01-01
    • 2012-01-08
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多