【问题标题】:Is there a faster way to print to a TextBox than AppendText?有没有比 AppendText 更快的打印到 TextBox 的方法?
【发布时间】:2015-12-10 22:12:30
【问题描述】:

我有一个后台线程,它正在从设备读取消息并将它们格式化并将它们传递给生产者/消费者集合的“消费者”节点,然后将所有消息打印到字符串中。我遇到的问题是日志记录在进程结束之后有点滞后,所以我试图找到一种更快的方法来打印到屏幕上。这是我的消费者方法:

private void DisplayMessages(BlockingCollection<string[]> messages)
{
    try
    {
        foreach (var item in messages.GetConsumingEnumerable(_cancellationTokenSource.Token))
        {
            this.Invoke((MethodInvoker)delegate
            {
                outputTextBox.AppendText(String.Join(Environment.NewLine, item) + Environment.NewLine);
            });
        }
    }
    catch (OperationCanceledException)
    {
        //TODO:
    }
}

我已经对我的生产者方法进行了一些基准测试,甚至登录到控制台,看起来写入这个 TextBox 的速度有点慢。在每个过程中,我记录了大约 61,000 行,大约 60 个字符长。

我研究过使用 .AppendText() 比使用 textBox.Text += newText 更好,因为这会重置整个 TextBox 的文本。我正在寻找一种解决方案,它可能包括更快的打印到 TB 的方法(或者更适合快速记录的 UI 元素?),或者如果使用 String.Join(Environment.NewLine, item) 效率低下并且可以以任何方式加速。

【问题讨论】:

  • 或许使用字符串生成器而不是连接字符串?
  • 所以你调用这个调用方法 61000 次?您正在用许多请求的方式淹没消息泵。您需要以基于时间的方式更新 UI。
  • 尝试在不先调用的情况下执行此操作。
  • 只是一些提示:如果尚未使用“WordWrap=false”,则可以提供帮助(来自:stackoverflow.com/a/11276778/265165
  • @McAdam331 for 1,向您的应用程序添加一个按钮以启动该文件的记事本++ 进程。其余的,你甚至可能不需要 lock 或 list; 可能在您的 RAM 上使用每个 GUI 更新 stackoverflow.com/questions/3817477/… 直接读取日志文件会更简单、更容易。同样作为另一个 UX 想法,一个 hex/ascii/"parsed" 单选按钮很不错。

标签: c# winforms performance task-parallel-library producer-consumer


【解决方案1】:

String.Join 并不是低效的。它被调用的方式导致它被调用 N 次(对于集合中的每个消息 arrau 调用一次)而不是只调用一次。您可以通过使用SelectMany 展平集合来避免这种情况。 SelectMany 将 IEnumerable 作为输入并返回其中的每个单独的项目:

var allLines=messages.SelectMany(msg=>msg);
var bigText=String.Join(allLines,Environment.NewLine);

虽然使用如此大的文本框会非常困难。您应该考虑使用虚拟化网格或列表框,添加过滤器和搜索功能,以便用户更轻松地找到他们想要的消息。

另一种选择可能是简单地将行分配给TextBox.Lines 属性而不创建字符串:

var allLines=messages.SelectMany(msg=>msg);
outputTextBox.Lines=allLines.ToArray();

【讨论】:

    【解决方案2】:

    O(n^2) 性能的代码预计会很慢。

    如果您不能使用String.Join 构建整个输出一次,请考虑使用面向列表的控件甚至网格。如果行数非常多,大多数列表控件和网格都有“虚拟”模式,在这种模式下,文本实际上是按需请求的。

    【讨论】:

    • 我将研究虚拟模式。我不知道这方面的来源,但一位同事告诉我,他们遇到了 ListBox 大约 65,000 个项目的问题(我在这里接近它,我们的许多闪存进程将有超过 65,000 个项目)所以我没有尝试那。我会考虑一个DataGridView。我不确定什么会比 TextBox 更快或更慢,但我会尝试一下。
    • 如果 65K+ 行是您的正常情况网格可能是更好的选择 - 尝试并测量(不要仅使用 DataGridView 来限制您的搜索)。
    猜你喜欢
    • 2017-07-19
    • 2021-01-08
    • 2018-12-05
    • 1970-01-01
    • 2018-08-09
    • 2011-03-24
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多