使用WPF显示流富文本 [英] Displaying streaming rich text with WPF

查看:58
本文介绍了使用WPF显示流富文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个WPF应用程序,该应用程序通过套接字连接到设备并获取流文本数据(每秒大约1条消息).然后,该数据显示在UI上.用户可以创建诸如如果数据包含'abc'突出显示该行" …使其变为粗体" 之类的规则,那么纯文本输出将不起作用,需要成为丰富"文本.

我目前的解决方案是使用我的ViewModel中的FlowDocument 包含格式化的输出.视图具有绑定的 FlowDocumentScrollViewer 到ViewModel中的FlowDocument.

这可行,但是当FlowDocument变大(〜6,000行)时,性能开始下降.当前的算法将行数的上限限制为10,000,但是事情甚至变得更糟,以至于该应用程序无法使用.一旦达到10,000行,我就为添加的每一行删除一条行,导致FlowDocumentScrollViewer为每条新行获得2条更新通知.

我试图找到一种批量删除的方法(当我们达到10,000行时,删除最旧的1,000行),但是FlowDocument上没有批量删除.循环执行1000次并执行删除操作会产生1,000条更新通知,并锁定UI.

那是我的问题,这是我的问题:

使用WPF显示流式富文本内容的最佳方法是什么?我每秒收到1条消息,每条消息是150个字符,我想保留最后10000条消息.我会以错误的方式处理吗?还有其他性能更好的控件/对象吗?

编辑:还有更多要求

  • 需要能够打印输出文本
  • 需要能够选择和复制输出文本,以便可以将其粘贴到另一个文档中

解决方案

性能下降似乎是由FlowDocument中的大量块引起的.对于收到的每条消息,我都在创建一个Run,将其添加到Paragraph中并将该段落添加到文档中.

我更改了算法,现在它创建了一个段落,然后向该段落添加了250次运行,然后创建了一个新的段落...添加了250次运行...,依此类推.这实际上将块的数量减少了一半.

当我达到最大行数(10,000)时,这也有一个额外的好处.我可以删除最旧的段落,然后立即删除最旧的250行,而不必为添加的每个新行删除单个行(并固定CPU),而只需立即删除最旧的250行即可.

此相对简单的更改使性能很好地处于可接受的范围内.现在,CPU不再相对固定CPU和锁定UI,而是保持相对较低的峰值(约15%).

I have a WPF application that connects via a socket to a device and gets streaming text data (approx 1 message per second). This data is then displayed on the UI. The user can create rules like "If the data contains 'abc' highlight the line" or "…make it bold", so plain text output will not do, it needs to be "rich" text.

My current solution to this is to have a FlowDocument in my ViewModel that contains the formatted output. The View has a FlowDocumentScrollViewer that is bound to the FlowDocument in the ViewModel.

This works, but when the FlowDocument gets large (~6,000 lines) performance starts to degrade. The current algorithm caps the number of lines at 10,000, but then things get even worse, to the point where the app is unusable. Once it reaches 10,000 lines, then I remove a line for every line that is added resulting in the FlowDocumentScrollViewer getting 2 update notifications for every new line.

I tried to find a way to batch delete (when we reach 10,000 lines delete the oldest 1,000 lines), but there is no bulk delete on the FlowDocument. Looping 1,000 times and doing the delete results in 1,000 update notifications and locks up the UI.

That’s my problem, here’s my question:

What is the best way to display streaming rich text content with WPF? I get ~ 1 message per second, each message is ~150 characters, and I want to keep the last 10000 messages. Am I going about this the wrong way? Are there other controls/objects that would perform better?

EDIT: Here are some more requirements

  • Need to be able to print the output text
  • Need to be able to select and copy the output text so it can be pasted into another document

解决方案

The performance breakdown seemed to be caused by the high number of Blocks in the FlowDocument. For every message received I was creating a Run, adding that run to a Paragraph and adding the paragraph to the document.

I changed the algorithm so now it creates a Paragraph then adds 250 Runs to that Paragraph, then creates a new Paragraph ... adds 250 Runs ... and so on. This essentially cuts the number of blocks in half.

This also has an added benefit when I reach the max number of lines (10,000). Instead of deleting a single line for each new line added (and pegging the CPU), I can just delete the oldest Paragraph and that instantly deletes the oldest 250 lines.

This relatively simple change brought the performance well within the acceptable range. Instead of pegging the CPU and locking up the UI, now the CPU stays relatively low with spikes around 15%.

这篇关于使用WPF显示流富文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆