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

C#存储和输出字符串列表的最佳方式,c#,wpf,mvvm,C#,Wpf,Mvvm,目前,我的应用程序有一个文本框,可以在屏幕上显示500行实时日志。由于应用程序后面有很多繁重的任务,所以我尝试尽可能地为我的应用程序改进这一部分。欢迎任何建议。谢谢 WPF: 方法2(更好的性能): 列出msgList; 私有void OutputMessage(字符串消息) { //结果 //1000行31ms //10000行377ms 如果(!string.IsNullOrEmpty(msg)) { 字符串msgWithTimeStamp=System.DateTime.Now.ToStr

目前,我的应用程序有一个文本框,可以在屏幕上显示500行实时日志。由于应用程序后面有很多繁重的任务,所以我尝试尽可能地为我的应用程序改进这一部分。欢迎任何建议。谢谢

WPF:

方法2(更好的性能):

列出msgList;
私有void OutputMessage(字符串消息)
{
//结果
//1000行31ms
//10000行377ms
如果(!string.IsNullOrEmpty(msg))
{
字符串msgWithTimeStamp=System.DateTime.Now.ToString()+“:\t”+msg;
添加(msgWithTimeStamp);
如果(msgList.Count>500)
msgList.RemoveAt(0);
StatusMessage=String.Join(“\n”,msgList);
}
}

最大的问题是以下几行:

StatusMessage = String.Join("\n", msgList);
这意味着您每次更新字符串的主列表时都要重新生成整个字符串,并在整个列表中循环,分配新的内存缓冲区,直到缓冲区足够大以填充整个字符串(所有500行)。当您的消息列表增加到500行时,这意味着下一条消息将导致500个缓冲区分配,以便重新生成完整的字符串

更好的方法是在消息列表旁边维护一个
StringBuilder
(在
msgList
变量中)
StringBuilder
在修改消息时如何分配缓冲区方面非常智能

我编写了以下代码段,在我的机器上,将一条新消息添加到已包含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();
    }
}

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

最大的问题是以下几行:

StatusMessage = String.Join("\n", msgList);
这意味着您每次更新字符串的主列表时都要重新生成整个字符串,并在整个列表中循环,分配新的内存缓冲区,直到缓冲区足够大以填充整个字符串(所有500行)。当您的消息列表增加到500行时,这意味着下一条消息将导致500个缓冲区分配,以便重新生成完整的字符串

更好的方法是在消息列表旁边维护一个
StringBuilder
(在
msgList
变量中)
StringBuilder
在修改消息时如何分配缓冲区方面非常智能

我编写了以下代码段,在我的机器上,将一条新消息添加到已包含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();
    }
}

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

您可以使用Items控件并将其ItemsSource数据绑定到ObservableCollection,而不是使用文本框。然后,您只需将每个新消息附加到ObservableCollection,ItemsControl将自动更新,以在其列表末尾显示新条目。

您可以使用ItemsControl并将其ItemsSource数据绑定到ObservableCollection,而不必使用文本框。然后您只需将每个新消息附加到ObservableCollection,ItemsControl将自动更新,以在其列表末尾显示新条目。

我认为这个问题不适合stackoverflow。这里我们讨论的是坏代码,所以,如果你的代码确实在工作,你可以试着问这个问题,我认为这个问题不适合stackoverflow。这里我们讨论的是中断的代码,因此,如果您的代码实际工作,您可以尝试在我认为
Join
内部使用StringBuilder时问这个问题,但是StringBuilder的容量有限,并且每次达到该限制时,该容量都会扩展,从而导致新的内存分配。因此,一旦达到500行限制,您的方法将避免所有这些分配+1我认为,
Join
在内部使用StringBuilder,但StringBuilder的容量有限,每次达到限制时,该容量都会扩展,从而导致新的内存分配。因此,一旦达到500行限制,您的方法将避免所有这些分配+1绝对是一个好选项,尤其是与VirtualzingStackPanel结合使用时。绝对是一个好选项,尤其是与VirtualzingStackPanel结合使用时。
// 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();
    }
}