有没有比AppendText更快的方式打印到TextBox?

时间:2015-09-14 19:50:30

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

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

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)效率低下并且可以以任何方式加速。

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分: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();