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

标签 c# wpf xaml

我最近一直在开发一个 RTF 编辑器,它只是一个简单的 UserControl,它有一个 RichTextBox 和几个事件,比如 PreviewTextInputPreviewMouseUp

不过我注意到有些事情有点烦人。 每当调整 UI 大小时,RichTextBox 的性能绝对糟糕,并且 RichTextBox 有大量文本导致其环绕算法触发。

这给应用程序一种非常草率的感觉,就好像它没有得到很好的优化(即使它不是)。

起初我注意到在选择文本时性能受到影响,所以我没有使用 SelectionChanged 事件,而是决定使用 PreviewMouseUp 事件然后获取选择。

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

为了进一步测试,我决定注释掉我的 RichTextBox 并只包含一个没有定义属性的新 RichTextBox

<RichTextBox/>

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

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

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

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

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

我有点难过,因为我喜欢 WPF,但我确实发现一个或另一个对象与 WinForms 对象相比确实没有优化和/或不实用,RichTextBox 似乎是另一种情况:(

对于大量的文本,我深表歉意,但我真的很想把它整齐地记录下来,以防其他可怜的人遇到这个问题,并让你们看看我到目前为止所做的尝试。

最佳答案

解决此问题的一种方法可能是在调整窗口大小时切换到“无环绕”模式,但当用户完成调整大小时切换回正常模式。然后包装算法将在最后只执行一次,用户应该仍然对您的应用程序有流畅的感觉。示例代码:

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

关于c# - RichTextBox - UI 调整大小导致巨大的 CPU 负载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39849599/

相关文章:

c# - 使用 Setter 更新样式触发器中的自定义附加属性

wpf - 在 WPF 中仅使用 XAML 将元素定位在 Canvas 内的中心(而不是左上角)

c# - MessageBox.Show 的简单 "Login Attempt"问题

c# - 使用 Linq,如何将 Xml 解析为仅在构造函数中接受参数的 C# 对象?

c# - 在服务器或客户端按数据分组更好吗?

c# - .Net 中的网格生成库?

wpf - 定义我要打印的流程文档在页面上的位置为 'start' 和 'end'

c# - WPF MVVM 使用 BooleanToVisibilityConverter 隐藏按钮

c# - 在 WPF 中触发继承?

c# - List<Bar> 的 Json 反序列化中的属性 setter