为什么KeyUp和KeyDown事件变慢?
问题描述:
我在WPF窗口上使用KeyUp
和KeyDown
事件。为什么KeyUp和KeyDown事件变慢?
我还在此窗口的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);
}
我注意到元素的多我越慢得KeyUp
和KeyDown
事件。
当我在主窗口中有大约1000个UI元素时,control_KeyDown和control_KeyUp的代码在我敲击或释放键约半秒钟后执行。
这并不会让我感到意外,如果窗口内的动画也是滞后的,但事实并非如此。
- 帧率是在约55 fps的
- 动画保持光滑
- 在
CompositionTarget_Rendering
事件的计算持续时间不超过20毫秒。
似乎只有键盘事件轮询正受到恶劣条件的影响。
我的问题是:
- 什么是落后于WPF键盘操作的魔力:它为什么重条件,而不是渲染处理下得到laggy?
- 如何处理更好的键盘输入并避免这种情况?
编辑:
我写安迪评论启发的样本。您可以将其粘贴到新的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事件并且边框变为红色。
答
要到我的第二个问题作出回应,我已经找到一个替代的方式做一个全局键盘钩子:Using global keyboard hook (WH_KEYBOARD_LL) in WPF/C#
其Keyup
和Keydown
事件没有响应滞后,事件重CPU和图形负载下。
如果我设置一个新项目,创建一个新窗体并添加一个循环来创建50,000个文本框并挂钩主窗口的KeyDown事件,实际上我根本没有注意到任何延迟。这些嵌套控件? – Andy 2013-04-08 15:11:20
没有控件嵌套。您是否想尝试在CompositionTarget_Rendering事件中放置一些代码,以将一些随机文本放入TextBox中?我认为这将反映我的情况。想到50000个文本框是很多的。 – Larry 2013-04-08 15:14:33
不知道如果把文本框在一个虚拟容器像一个列表框将帮助? – Paparazzi 2013-04-08 17:50:16