RichTextBox - UI调整大小会导致巨大的CPU负载

时间:2016-10-04 10:10:10

标签: c# wpf xaml

我最近一直在开发一个RTF编辑器,它只是一个简单的UserControlRichTextBox有一些事件,如PreviewTextInputPreviewMouseUp。< / p>

我注意到有些烦人的东西。 每当调整UI大小并且RichTextBox有大量文本导致其包装算法触发时,RichTextBox的性能绝对非常糟糕。

这给应用程序带来了一种非常草率的感觉,好像它的优化程度很差(即使它不是)。

首先我注意到在选择Text时出现这种性能影响,因此我决定使用SelectionChanged事件而不是PreviewMouseUp事件,然后获取选择。

然后经过进一步测试后我发现调整大小也造成了巨大的负担。 我说的是负载范围在5%之间 - &gt;配备四核CPU运行频率为3.8GHz的30%!

为了进一步测试,我决定评论我的RichTextBox并仅包含一个没有定义属性的新RichTextBox

<RichTextBox/>

将其插入窗口,填充文本,然后调整窗口大小以使包装算法再次执行相同操作,使用率高达30%!

我尝试研究这个问题,大多数人最后建议将PageWidth设置为高值以防止换行:

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

我不想要,因为我编写的编辑器的前一版本是使用WinForms制作的,可以毫不费力地进行包装,我也希望在新的WPF版本中使用。

有没有其他人遇到过这个问题? 如果是的话,请您指出正确的方向,以消除硬件上的巨大压力?

我有点难过,因为我喜欢WPF,但我确实找到了一个或者另一个与WinForms对应物相比没有优化和/或不实用的对象,RichTextBox似乎是另一个其中一个案例:(

对于大量的文字感到抱歉,但我真的很想记录这个问题,以防其他一些可怜的灵魂面临这个问题,并且让你们看看我到目前为止所尝试的内容。

1 个答案:

答案 0 :(得分:7)

克服这个问题的一种方法可能是切换到&#34;没有换行&#34;调整窗口大小时的模式,但是当用户完成调整大小时 - 切换回正常模式。然后包装算法将在最后执行一次,用户仍然应该对您的应用程序有一个平稳的感觉。示例代码:

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