为什么KeyUp和KeyDown事件变慢?

时间:2013-04-08 14:21:34

标签: wpf keyboard-events

我在WPF窗口上使用KeyUpKeyDown事件。

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

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);
}

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

当我在主窗口中有大约1000个UI元素时,在我点击或释放密钥后大约半秒钟内执行control_KeyDown和control_KeyUp的代码。

如果窗口内的动画也是滞后的话,这不会让我感到惊讶,但事实并非如此。

  • 帧速率约为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以增加文本框的数量。在某个数量上,有比KeyUp或KeyDown更多的CompositionTarget_Rendering触发器。当按下一个键以查看边框的颜色变化时,它是非常明显的:键已关闭,然后几次触发Composition_Rendering,然后触发keydown事件并且边框变为红色。

1 个答案:

答案 0 :(得分:0)

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

它的KeyupKeydown事件在没有滞后的情况下响应,在CPU和图形负载过重的情况下发生事件。