2016-10-04 13 views
10

ja niedawno rozwijanie edytor RTF, który jest tylko prostą UserControl że ma RichTextBox z kilku wydarzeń, takich jak PreviewTextInput i PreviewMouseUp.RichTextBox - UI Resize powoduje ogromne obciążenia procesora

Zauważyłem jednak coś nieco irytującego. Wydajność RichTextBox jest absolutnie straszna za każdym razem, gdy zmienia się rozmiar interfejsu użytkownika, a RichTextBox ma dużo tekstu, aby wywołać jego algorytm owijający.

Daje to aplikacji naprawdę niechlujstwa, jakby była słabo zoptymalizowana (mimo że nie jest).

Najpierw zauważyłem to uderzenie wydajności podczas wybierania tekstu, więc zamiast używać zdarzenia SelectionChanged, zdecydowałem się użyć zdarzenia PreviewMouseUp, a następnie pobrać zaznaczenie.

Po dalszych testach okazało się, że zmiana rozmiaru spowodowała również duże obciążenia. I mówię o obciążeniach w zakresie od 5% do 30% za pomocą czterordzeniowego procesora pracującego z częstotliwością 3,8 GHz!

Aby dodatkowo przetestować go, postanowiłam skomentować mój RichTextBox i tylko to nowy RichTextBox bez określonej własności

<RichTextBox/> 

Wkładanie to do okna, wypełnienie z tekstem, a następnie zmiany rozmiaru okna do Algorytm Owijania zrobił to samo, nawet do 30% użycia!

Próbowałem badań na ten temat, a większość ludzi skończyło się polecając ustawiania PageWidth do wysokich wartości w celu uniknięcia dozowania:

richTextBox1.HorizontalScrollBarVisibility = ScrollBarVisibility.Visible; 
richTextBox1.Document.PageWidth = 1000; 

czego nie ma, ponieważ poprzednia wersja edytora Napisałem został zrobiony przy pomocy WinForms i mogłem zrobić Owijanie bez wysiłku, a także chcę go w nowej wersji WPF.

Czy ktoś jeszcze kiedykolwiek stanął w obliczu tego problemu? Jeśli tak, czy możesz wskazać mi właściwy kierunek, aby usunąć to ogromne obciążenie sprzętu?

Jestem trochę smutny, ponieważ uwielbiam WPF, ale znalazłem jeden lub drugi obiekt, który jest naprawdę nieoptymalizowany i/lub nie jest praktyczny w porównaniu do odpowiednika WinForm, RichTextBox wydaje się być jednym z tych przypadków :(

Niestety dla ogromnej ilości tekstu, ale naprawdę chciałem dokumentu ten starannie w przypadku jakiś inny biedny dusza stoi ten problem i dla was, aby zobaczyć, co starałem tak daleko.

Odpowiedz

7

One sposobem na pokonanie tego problemu może być przejście do trybu "bez zawijania" przy zmianie rozmiaru okna, ale kiedy użytkownik skończył zmianę rozmiaru - przełączyć się z powrotem do trybu normalnego, a następnie algorytm owijający zostanie wykonany tylko raz na końcu i Sery powinny nadal mieć łagodne odczucia odnośnie twojej aplikacji. Przykładowy kod:

public partial class MainWindow : Window 
{ 
    public MainWindow() { 
     InitializeComponent(); 
     this.SizeChanged += OnSizeChanged; 
    } 

    private Timer _timer; 
    private void OnSizeChanged(object sender, SizeChangedEventArgs e) { 
     // user started resizing - set large page width 
     textBox.Document.PageWidth = 1000; 
     // if we already setup timer - stop it and start all over 
     if (_timer != null) { 
      _timer.Dispose(); 
      _timer = null; 
     } 

     _timer = new Timer(_ => { 
      // this code will run 100ms after user _stopped_ resizing 
      Dispatcher.Invoke(() => 
      { 
       // reset page width back to allow wrapping algorithm to execute 
       textBox.Document.PageWidth = double.NaN; 
      }); 
     }, null, 100, Timeout.Infinite); 
    } 
} 
+0

Zabawne, że nie myślałem o oczywistym wyborze, który wiąże się z funkcją Resize Call, wydaje mi się, że jestem zbyt zmęczony. Wystąpił błąd w kodzie, w którym próbujesz wywołać btw, co poprawia: Dispatcher.Invoke (nowa akcja (() => {})); –

+0

Nawiasem mówiąc, używanie Timerów jest ryzykowne w tej sytuacji, ponieważ w zależności od wydajności komputera, zdarzenie może nadal być nieaktualne, w moim przypadku musiałem użyć 300 ms, aby uzyskać więcej lub mniej pracy, ale to zdecydowanie wskazało mi właściwy kierunek, zamierzam go zmienić, aby pasował do mojej konieczności, w końcu pozbywając się timerów. Dzięki. –

+0

Jeśli chcesz dowiedzieć się, jak to jest pod względem wydajności, pomogło mi to zmniejszyć obciążenie o 50%, teraz jest to 15% użycia podczas zmiany rozmiaru, jeśli dużo tekstu jest w środku, IMO RichTextBox to wielki bałagan w kategoriach wydajności, ponieważ wydaje się, że algorytm Wrap nie jest jedynym czynnikiem powodującym te problemy, tak czy inaczej, raz jeszcze dzięki za wskazanie mi we właściwym kierunku;) –

Powiązane problemy