WPF:我应该在我的Log中使用string ob StringBuilder

时间:2018-03-27 08:19:21

标签: wpf multithreading log4net

所以我有WPf个应用程序和Log4Net所以每次我想添加log时我都会这样添加:

log4net.Info("bla bla");

此外,我想添加记录器form,因此我创建了另一个form,并从我的主form我打开它:

LoggerForm loggerForm = new LoggerForm();
loggerForm.Show();

并创建Log object

public class LogEntry : PropertyChangedBase
{
    public string DateTime { get; set; }
    public int Index { get; set; }
    public string Source{ get; set; }
    public Level Level { get; set; }        
    public string Message { get; set; }
}

LogHelperLogEvent个对象放在List内,并将每个LogEvent添加到此List中:

public static class LogHelper
{
    public static ObservableCollection<LogEntry> LogEntries { get; set; }
    public static bool AddLogToList { get; set; }

    private static int Index;

    public static void AddLog(Level level, string message, string source)
    {
        if (AddLogToList)
        {
            Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                if (LogEntries.Count == 1000)
                    LogEntries.RemoveAt(0);

                LogEntry logEntry = new LogEntry()
                {
                    DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss,fff"),
                    Index = Index++,
                    Level = level,
                    Source = source,
                    Message = message.Trim()
                };

                LogEntries.Add(logEntry);
            }));
        }
    }
}

form注册到我的列表InitializeComponent之后,从我的记录器CollectionChanged开始:

LogHelper.AddLogToList = true;
LogHelper.LogEntries.CollectionChanged += LogEntries_CollectionChanged;

这一行:

LogHelper.AddLogToList = true;

表示我的记录器form已打开,因此我可以插入LogEvent iunto my List。

CollectionChanged:

每次在我的LogEvent中添加新的List我都会将ItemSource更新为ListView

ListView lvLogger;

private void LogEntries_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    lvLogger.ItemsSource = LogHelper.LogEntries;
}

好的,这些是我的问题:

  1. 每次我想创建新的Log时,我都会输入两次:

    log.Info("bla bla");
    LogHelper.AddLog(Level.Info, "bla bla", $"MyClassName\\MyMethodName"); 
    

    所以你可以看到我在这里使用了两次字符串,所以我想知道使用String.Builder代替string是否会更好?

  2. 我还想提一下,我通过不同的线程更新我的日志。

    1. 当我的记录器form关闭时,我注册到其结束event并清除我的LogEvent列表:

      private void MetroWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
      {
          LogHelper.AddLogToList = false;
          LogHelper.LogEntries.Clear();
      }
      

      所以我的问题是我应该在这里注册我的LogEntries_CollectionChanged事件:

      LogHelper.LogEntries.CollectionChanged - = LogEntries_CollectionChanged;

    2. 或者这是多余的?

2 个答案:

答案 0 :(得分:1)

1)如果您反复多次附加文本,则只能使用Stringbuilder。除非那是你正在做的事情,否则我只会使用一个字符串。 如果这是你正在做的事情,那么也许你不应该这样做。

查看你的代码,你似乎已经有了一个消息变量,所以我可能会对使用它两次的部分感到困惑。也许你不是在谈论消息。 我会将一个字符串传递给一个方法,并在那里的代码行中使用该变量。假设他们采用相同的方法。

log.Info(message);
LogHelper.AddLog(Level.Info, message, $"MyClassName\\MyMethodName");

2)我多次阅读这部分,令人困惑。但是,作为一般原则,如果您从不是私有成员的事件订阅事件,那么您应该取消订阅该事件以避免任何内存泄漏。因此,如果集合是由不同的窗口或其他东西新建的,那么您应该取消订阅该处理程序,以便在您不再需要该窗口的实例时可以进行垃圾收集。

通过评论中的进一步说明,很明显您可以在减少日期时间内对集合进行排序,并在顶部查看最新的日志条目。这将完全避免collectionchanged事件处理程序。收集视图的排序: https://social.technet.microsoft.com/wiki/contents/articles/26673.wpf-collectionview-tips.aspx#Sorting

经过更多解释...... 看来文本文件是用于显示的。 我认为你应该完全忘记文本文件并使用observablecollection作为循环列表。

您正在调用logentries上的add方法:

LogEntries.Add(logEntry);

它的作用是附加到该集合。您可以使用insert。

插入特定索引
LogEntries.Insert(0, logEntry);

这增加了该系列的“顶级”。 我认为这也可以避免排序。 你不希望那个集合变得庞大,所以一旦你打了一个数字(比如说100),你就可以删除最旧的。

LogEntries.RemoveItem(100);

请记住首先检查您是否有超过100个条目,否则会出错。

您可能需要考虑对任何其他问题进行更全面的解释。我们只知道你告诉我们什么,人们不太可能坐在那里思考你正在做什么足够长的时间才能意识到......“嘿,这就是所有的日志和文件可能会很大”。

答案 1 :(得分:0)

使用StringBuilder不会减少您的代码。如果您想要更少的代码,请将log4net.Info("bla bla");放在LogHelper中,或创建同时执行这两项任务的内容。

StringBuilder与此Andy Stringbuilder is only worth using if you're repeatedly appending text numerous times.

无关

更多信息 - &gt; String vs Stringbuilder