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.
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
Ż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
Zastanawiasz się, czy wstawienie TextBoxów do kontenera wirtualizacyjnego, takiego jak ListBox, pomogłoby? – Paparazzi