C#存储和输出字符串列表的最佳方法

时间:2019-01-30 02:38:17

标签: c# wpf mvvm

当前,我的应用程序有一个文本框,它将在屏幕上显示500行实时日志记录。由于应用程序后面有很多繁重的任务,因此我会尽我所能为我的应用程序改进这一部分。打开任何建议。谢谢。

WPF:

<TextBox Text="{Binding StatusMessage}" TextWrapping="Wrap" AcceptsReturn="True" />

方法1:

private void OutputMessage(string msg)
{
    //Result
    //1000  Lines     108ms
    //10000 Lines    1687ms
    if(!string.IsNullOrEmpty(msg))
    {
        string msgWithTimeStamp = System.DateTime.Now.ToString() + ": \t" + msg;

        int msgLine = 0;
        if (!string.IsNullOrEmpty(StatusMessage))
        {
            //Only show 500 lines of latest messages...
            msgLine = StatusMessage.Count(m => m == '\n');
            if (msgLine > 500)
                StatusMessage = StatusMessage.Remove(0, StatusMessage.IndexOf("\n") + 1);

            StatusMessage = StatusMessage + "\n" + msgWithTimeStamp;
        }
        else
            StatusMessage = msgWithTimeStamp;
    }
}

方法2(效果更好):

List<string> msgList;
private void OutputMessage(string msg)
{
    //Result
    //1000  Lines     31ms
    //10000 Lines    377ms
    if (!string.IsNullOrEmpty(msg))
    {
        string msgWithTimeStamp = System.DateTime.Now.ToString() + ": \t" + msg;
        msgList.Add(msgWithTimeStamp);

        if (msgList.Count > 500)
            msgList.RemoveAt(0);

        StatusMessage = String.Join("\n", msgList);
    }
}

2 个答案:

答案 0 :(得分:4)

代替使用TextBox,可以使用ItemsControl,并将数据的ItemsSource绑定到ObservableCollection。然后,您只需将每条新消息附加到ObservableCollection,ItemsControl就会自动更新,以在列表的末尾显示新条目。

答案 1 :(得分:3)

最大的问题是以下几行:

StatusMessage = String.Join("\n", msgList);

这意味着您在每次更新主字符串列表时都将重建整个字符串,并循环遍历整个列表,分配新的内存缓冲区,直到缓冲区足够大以填充整个字符串(所有500行)为止。当您的消息列表增加到500行时,这意味着下一条消息将导致500个缓冲区分配,仅用于重建完整的字符串。

一种更好的方法是在邮件列表旁边(在StringBuilder变量中)维护一个msgListStringBuilder擅长在您修改邮件时分配缓冲区。

我写了以下代码段,在我的机器上,将新消息添加到列表中已经有500条消息的时间不到一毫秒。

// Somewhere in your code, probably next to your [msgList] variable...
private StringBuilder sb = new StringBuilder();

private void OutputMessage(string msg)
{
    if (!string.IsNullOrEmpty(msg))
    {
        string msgWithTimeStamp = System.DateTime.Now.ToString() + ": \t" + msg;
        msgList.Add(msgWithTimeStamp);
        sb.AppendLine(msgWithTimeStamp);

        if (msgList.Count > 500)
        {
            sb.Remove(0, msgList[0].Length + 2); // The +2 is to account for the new line and carriage return characters.
            msgList.RemoveAt(0);
        }

        statusMessage = sb.ToString();
    }
}

此方法的唯一缺点是两次维护同一组消息。