C# 将大量文本写入文本框

C# 将大量文本写入文本框,c#,winforms,textbox,C#,Winforms,Textbox,我正在向.net windows窗体应用程序中的文本框写入大量格式化文本的日志 一旦数据超过几个兆欧,速度就会变慢。因为我在追加字符串,所以每次都必须重新分配,对吗?我只需要将值设置到文本框一次,但在我的代码中,我执行了数万次line+=data 有没有更快的方法?也许是另一种控制?是否有我可以使用的链表字符串类型?与StringBuilder一起构建字符串,然后使用toString()将其转换为字符串,并将其分配给文本框。如果文本框以增量方式添加,例如日志输出,StringBuilder将不会

我正在向.net windows窗体应用程序中的文本框写入大量格式化文本的日志

一旦数据超过几个兆欧,速度就会变慢。因为我在追加字符串,所以每次都必须重新分配,对吗?我只需要将值设置到文本框一次,但在我的代码中,我执行了数万次
line+=data


有没有更快的方法?也许是另一种控制?是否有我可以使用的链表字符串类型?

StringBuilder一起构建字符串,然后使用
toString()
将其转换为字符串,并将其分配给文本框。

如果文本框以增量方式添加,例如日志输出,StringBuilder将不会有帮助

但是,如果上述情况属实,并且您的更新足够频繁,那么您应该缓存一些更新,然后在一个步骤中附加它们(而不是不断附加)。这将为您节省许多字符串重新分配。。。然后StringBuilder会很有帮助

注:

  • 创建一个类范围的StringBuilder成员(_sb)
  • 启动计时器(或使用计数器)
  • 将文本更新附加到_sb
  • 当计时器滴答作响或某个计数器达到重置并附加到 文本框
  • 从#1重新启动进程

  • 还没有人提到虚拟化,虚拟化是为海量数据提供可预测性能的唯一方法。即使使用
    StringBuilder
    并每隔半秒将其转换为字符串,一旦日志变得足够大,也会非常缓慢

    使用数据虚拟化,您将只在内存中保存所需的数据(即用户可以看到的数据,或者在两侧多保存一点),而其余数据将存储在磁盘上。旧数据会随着新数据的到来而“滚出”内存

    为了使
    文本框
    看起来好像有很多数据在里面,您可以告诉它有。当用户滚动时,您将使用来自底层源的相关数据(使用随机文件访问)替换缓冲区中的数据。因此,您的UI将监视文件,而不是侦听日志事件


    当然,这比简单地使用
    StringBuilder
    要做的工作多得多,但我认为这值得一提,以防万一。

    在连接的同时,为什么不使用StringBuilder,一旦设置完成,它就会连接到文本框。Text?@Alfred:看起来你建议的一个小改动是最有效的。不同之处在于,StringBuilder将用于累积文本,然后用AppendText()将文本追加到文本框中,然后清除StringBuilder。可能StringBuffer是我从未听说过的类,但我敢打赌,更可能是您指StringBufferRong语言,
    StringBuffer
    是java。=)虽然您的答案肯定是相关的,但我认为我只需要在文本框中设置一次值,但在我的代码中,我执行了数万次line+=数据。这意味着这不会是他具体问题的答案。@Marc:事实上,保罗的答案很好。一个线程锁定SB,附加到它,解锁。它做了很多次。UI线程可以每秒轮询少量次,锁定SB,获取ToString并清除它。通过这种方式,UI更新频率完全独立于连接频率。如果您仔细查看Paul Sasik的答案,包括我的评论,我想您会发现,使用大字符串时,它不会变慢。这是因为我们在写入文本框时仍然使用AppendText,并一直清除StringBuilder。@Steven:但是
    TextBox
    仍然拥有所有数据,因此您的数据量仍然受到限制。虚拟化消除了这一点,因为它只查看整个数据集的一个小窗口。您实际上只受磁盘空间的限制。任何成本/收益分析都必须包括成本。虚拟化文本框的用处要小得多,因为你甚至不能做简单的事情,比如Ctrl+A、Ctrl+C。虚拟化在一些情况下是合适的,比如连接到数据库表的网格。@Steven:我只是把它作为一个选项指出。如果要实施数据虚拟化,那是因为您拥有大量数据。在这种情况下,您不希望Ctrl+A起作用,因为用户可能会射中自己的脚。即使您确实希望它工作(比如,如果数据小于10MB),您仍然可以通过虚拟化选择来实现。或者,如果用户准备将大量文本(从文件中)复制到剪贴板上,您可以警告用户。公平地说,对于如何处理无限量的数据,数据虚拟化将是一个正确的通用答案。我会投赞成票,让大家注意到。