WPF ウィンドウでKeyUp
andイベントを使用しています。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 要素がある場合、キーを押すか離してから約 0.5 秒後に、control_KeyDown と control_KeyUp の両方のコードが実行されます。
ウィンドウ内のアニメーションも遅れていたとしても、これは驚くことではありませんが、そうではありません。
- フレームレートは約55fps
- アニメーションは滑らかなままです
- イベントの計算は
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 イベントがトリガーされ、境界線が赤に変わります。