RichTextBox - изменение размера пользовательского интерфейса приводит к огромной загрузке процессора
Недавно я разрабатывал RTF-редактор, который представляет собой простой UserControl
, который имеет RichTextBox
с несколькими событиями, такими как PreviewTextInput
и PreviewMouseUp
.
Я заметил что-то слегка раздражающее.
Производительность RichTextBox
абсолютно ужасна всякий раз, когда пользовательский интерфейс изменяется, а RichTextBox
имеет много текста, чтобы вызвать его алгоритм обертывания.
Это дает Приложению действительно неаккуратное чувство, как будто оно плохо оптимизировано (хотя это не так).
Сначала я заметил, что это удар производительности при выборе "Текст", поэтому вместо использования события SelectionChanged
я решил использовать событие PreviewMouseUp
, а затем выбрать Selection.
Затем после дальнейшего тестирования выяснилось, что изменение размера также вызвало огромные нагрузки.
И я говорю о нагрузках от 5% до 30% с четырехъядерным процессором на 3,8 ГГц!
Чтобы еще раз проверить это, я решил прокомментировать мой RichTextBox
и включить только новый RichTextBox
без определенного свойства
<RichTextBox/>
Вставка этого в окно, заполнение текстом, а затем изменение размера окна, чтобы заставить алгоритм обертывания сделать то же самое, до 30% использования!
Я попытался исследовать этот вопрос, и большинство людей решили рекомендовать устанавливать значения PageWidth
на высокие значения, чтобы предотвратить Wrapping:
richTextBox1.HorizontalScrollBarVisibility = ScrollBarVisibility.Visible;
richTextBox1.Document.PageWidth = 1000;
Что я не хочу, так как предыдущая версия Редактора, которую я написал, была сделана с помощью WinForms и могла легко сделать Wrapping, и я также хочу ее в новой версии WPF.
Кто-нибудь еще сталкивался с этой проблемой?
Если да, не могли бы вы указать мне в правильном направлении, чтобы устранить эту огромную нагрузку на оборудование?
Мне немного грустно, потому что я люблю WPF, но я нашел тот или другой объект, который действительно неоптимизирован и/или не практичен по сравнению с копией WinForms, RichTextBox
кажется еще одним из тех случаи: (
Извините за огромное количество текста, но я очень хотел документально описать это на случай, если какая-то другая бедная душа столкнется с этой проблемой, и вы, ребята, увидите, что я пробовал до сих пор.
Ответы
Ответ 1
Одним из способов преодоления этой проблемы может быть переход на режим "без обертки" при изменении размера окна, но когда пользователь закончил изменение размера - вернитесь в обычный режим. Затем алгоритм обертки будет выполняться только один раз в конце, и пользователи все равно должны иметь гладкое представление о вашем приложении. Пример кода:
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);
}
}