7

WPF ウィンドウでKeyUpandイベントを使用しています。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_Rendering20 ミリ秒を超えません。

キーボード イベント ポーリングだけが重い状態に陥っているようです。

私の質問は次のとおりです。

  • 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 イベントがトリガーされ、境界線が赤に変わります。

4

1 に答える 1