UI大小调整导致巨大的CPU负载
本文关键字:巨大 CPU 负载 调整 UI | 更新日期: 2023-09-27 18:11:29
我最近一直在开发一个RTF编辑器,这只是一个简单的UserControl
,它有一个RichTextBox
与一对事件,如PreviewTextInput
和PreviewMouseUp
。
我注意到一些有点烦人的事情。当UI被调整大小时,RichTextBox
的性能是绝对糟糕的,RichTextBox
有很多文本导致它的换行算法着火。
这会给应用程序一种非常草率的感觉,就好像它优化得很差(即使它不是)。
起初,我注意到在选择文本时性能受到影响,所以我决定使用PreviewMouseUp
事件,而不是使用SelectionChanged
事件,然后获取选择。
然后经过进一步的测试,我发现调整大小也造成了巨大的负载。我说的是负载在5% -> 30%之间,四核CPU运行在3.8GHz!
为了进一步测试它,我决定注释掉我的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);
}
}