2013-04-08 15 views
7

Używam zdarzeń KeyUp i KeyDown w oknie WPF.Dlaczego zdarzenia KeyUp i KeyDown stają się wolniejsze?

Mam również wiele wywołań w zdarzeniu CompositionTarget_Rendering tego okna, które tworzy UIElements i ożywiają je. Odbywa się to przez klasę silnika poniżej:

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

Zauważyłem, że im więcej elementów mam, tym wolniej się KeyUp i KeyDown wydarzenia.

Kiedy mam około 1000 UIelements w głównym oknie, , kod obu control_KeyDown i control_KeyUp jest wykonywany około pół sekundy po tym, jak uderzyłem lub zwolniono klucz.

Nie zdziwiłbym się, gdyby animacje w oknie także były zbyt niepewne, ale tak nie jest.

  • Prędkość odtwarzania jest na poziomie około 55 fps
  • Animacja pozostaje gładka
  • obliczeń w przypadku CompositionTarget_Rendering nie trwa więcej niż 20 milisekund.

Wygląda na to, że tylko sondowanie zdarzeń na klawiaturze cierpi na ciężkie warunki.

Moje pytanie to:

  • Czym jest magia za obsługę klawiatury w WPF: dlaczego jest coraz laggy pod ciężkim stanie, gdy nie proces renderowania?
  • Jak mogę obsłużyć lepsze dane wejściowe klawiatury i tego uniknąć?

EDIT:

pisałem próbkę inspirowany Andy komentarza. Możesz skopiować wkleić go do głównego systemu Windows świeżej aplikacji WPF. Zmienia kolor okna, gdy klawisz jest w dół lub w górę, i wypełnia on jak najwięcej pól tekstowych w zdarzeniu 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(); 
    } 
} 

W zależności od wydajności urządzenia, zmień 2000, aby zwiększyć liczbę pól tekstowych. W pewnej ilości jest więcej wyzwalaczy CompositionTarget_Rendering niż KeyUp lub KeyDown. Jest on dość widoczny po naciśnięciu klawisza, aby zobaczyć zmianę koloru obramowania: klawisz jest wyłączony, a funkcja Composition_Rendering jest uruchamiana kilka razy, a następnie wywoływane jest zdarzenie keydown, a obramowanie zmienia się na czerwone.

+0

Jeśli skonfiguruję nowy projekt, utwórz nowy formularz i dodaj pętlę, aby utworzyć 50 000 pól tekstowych i przechwycić główne zdarzenie KeyDown w systemie Windows, w rzeczywistości nie zauważam żadnego opóźnienia. Czy są to zagnieżdżone kontrolki? – Andy

+1

Żadne elementy sterujące nie są zagnieżdżone.Czy chcesz spróbować umieścić jakiś kod w zdarzeniu CompositionTarget_Rendering, aby umieścić losowy tekst w TextBox? Myślę, że to odzwierciedli warunki, które mam. 50000 pól tekstowych to dużo, pomyślał. – Larry

+0

Zastanawiasz się, czy wstawienie TextBoxów do kontenera wirtualizacyjnego, takiego jak ListBox, pomogłoby? – Paparazzi

Odpowiedz

Powiązane problemy