C# TextBox.ScrollToEnd花费的时间太长

C# TextBox.ScrollToEnd花费的时间太长,c#,wpf,.net-4.0,textbox,C#,Wpf,.net 4.0,Textbox,我有一个LogTextBox类用于显示日志消息: public class LogTextBox : TextBox { int maxMessageCount, messageCount; //number of characters for each message List<int> messageLengths; public LogTextBox(int maxMessageCount) { this.messag

我有一个LogTextBox类用于显示日志消息:

public class LogTextBox : TextBox
{
    int maxMessageCount, messageCount;

    //number of characters for each message
    List<int> messageLengths;

    public LogTextBox(int maxMessageCount)
    {
        this.messageCount = 0;
        this.maxMessageCount = maxMessageCount;
        this.messageLengths = new List<int>();

        IsReadOnly = true;
        IsUndoEnabled = false;
    }

    public void Log(string message)
    {
        if (messageCount >= maxMessageCount)
        {
            Dispatcher.Invoke((Action)delegate()
            {
                //statement 1
                string text = Text.Remove(0, messageLengths[0]);

                //statement 2
                Text = text + message + '\n';

                //statement 3
                ScrollToEnd();
            });

            messageLengths.RemoveAt(0);
            messageLengths.Add(message.Length + 1);
        }
        else
        {
            Dispatcher.Invoke((Action)delegate()
            {
                AppendText(message + '\n');
                ScrollToEnd();
            });

            messageLengths.Add(message.Length + 1);
            messageCount++;
        }
    }
}

public class Test
{
    public LogTextBox logView;

    public Timer timer;

    [STAThread]
    public static void Main()
    {
        Application app = new Application();
        Test test = new Test();

        test.logView = new LogTextBox(200);

        test.timer = new Timer(200);
        test.timer.Elapsed += new ElapsedEventHandler(test.timer_Elapsed);
        test.timer.Start();

        app.Run(main);
    }

    int line = 0;
    void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        logView.Log(GetMessage(line++));
    }

    private string GetMessage(int line)
    {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 1000; i++)
            builder.Append(line + " ");

        builder.Append('\n');

        return builder.ToString();
    }
}

如果易于阅读是主要的文档使用场景。 然后你可以试着使用

注:本流程文档旨在优化查看和可读性。 RichText box表示对FlowDocument对象进行操作的丰富编辑控件

编辑:

如果您不希望应用程序中的搜索结果超过上万条,那么到目前为止,TextBlock控件或只读多行文本框就足够了。 TextBox类有一个AppendText方法,它应该足够快。您不必删除第一条消息

您可以考虑使用不同的文本框控件。 这是一个用于SharpDevelop的Wpf文本编辑器,完全从头开始。它被称为AvalonEdit,codeproject上有一篇好文章: 似乎他已经对大型内容进行了优化


您是否尝试过将报表2从

       //statement 2
       Text = text + message + '\n';

?


这只是一个猜测,但由于编写的语句2每次都分配一个新的字符串对象,因此垃圾收集器可能正在启动以释放旧字符串。我相信AppendText是以避免中间分配的方式实现的。

为什么不考虑使用不同的文本框控件? 您可以尝试支持文本突出显示的,您可以在这里阅读


本地WPF richtext控件似乎更快。

我找到了logbox.ScrollToVerticalOffsetdouble.MaxValue;比logbox.ScrollToEnd;快1/3;。可能是因为它避免了对UpdateLayout的内部调用。

FlowDocument不是从TextBoxBase派生的。有4个控件支持查看FlowDocument:FlowDocumentReader、FlowDocumentPageViewer、RichTextBox和FlowDocumentScrollViewer。只有RichTextBox源于TextBoxBase并具有ScrollToEnd方法,但我怀疑它能否提供更好的性能,因为它比TextBox控件更重。@AlpHancıoğlu:啊!,我的错!同意,FlowDocument不是从TextBoxBase继承的。更新我的答案。。谢谢如果我不必从开头删除邮件,我会这么做。这就是为什么我调用'string text=text.Remove0,messagelength[0];'在报表2之前。
       //statement 2
       Text = text + message + '\n';
AppendText(message);
AppendText('\n');