WPF:我应该在我的日志中使用 string ob StringBuilder
WPF: should i use string ob StringBuilder with my Log
所以我有 WPf
应用程序和 Log4Net
所以每次我想添加 log
我只是这样添加:
log4net.Info("bla bla");
另外我想添加记录器 form
所以我创建了另一个 form
并且从我的主 form
我这样打开它:
LoggerForm loggerForm = new LoggerForm();
loggerForm.Show();
并创建日志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; }
}
和 LogHelper
将此 LogEvent
objects 保存在 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
插入我的列表。
收藏已更改:
每次将新 LogEvent
添加到我的 List
时,我都会将我的 ItemSource
更新到我的 ListView
:
ListView lvLogger;
private void LogEntries_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
lvLogger.ItemsSource = LogHelper.LogEntries;
}
好的,这些是我的问题:
每次我想创建新的Log
我输入两次:
log.Info("bla bla");
LogHelper.AddLog(Level.Info, "bla bla", $"MyClassName\MyMethodName");
所以你可以看到我在这里使用了两次字符串,所以我想知道使用 String.Builder
代替 string
是否更好?
我还想提一下,我通过不同的线程更新我的日志。
当我的 Logger 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;
或者这是多余的?
1) Stringbuilder 只有在您多次重复附加文本时才值得使用。除非那是你正在做的,否则我只会使用一个字符串。
如果这是您正在做的事情,那么也许您不应该这样做。
看看你的代码,你似乎已经有了一个消息变量,所以我可能对这部分关于使用它两次的内容感到有点困惑。也许你不是在谈论消息。
我会将一个字符串传递给一个方法,并在你的两行代码中使用该变量。假设他们使用相同的方法。
log.Info(message);
LogHelper.AddLog(Level.Info, message, $"MyClassName\MyMethodName");
2) 这部分我看了好几遍,感觉很混乱。不过,作为一般原则,如果您从非私有成员订阅事件,那么您应该取消订阅该事件以避免任何内存泄漏。因此,如果 collection 由不同的 window 或其他东西更新,那么您应该取消订阅该处理程序,这样 window 的实例可以在您不再需要它时被垃圾收集.
根据评论中的进一步解释,很明显您可以按递减的日期时间对 collection 进行排序,然后在顶部查看最新的日志条目。这将避免 collection 完全更改事件处理程序。 collection视图排序:
https://social.technet.microsoft.com/wiki/contents/articles/26673.wpf-collectionview-tips.aspx#Sorting
经过更多解释...
似乎文本文件是用于显示的。
我认为你应该完全忘记文本文件并使用 observablecollection 作为循环列表。
您正在对日志调用 add 方法:
LogEntries.Add(logEntry);
所做的是附加到 collection。您可以改为使用 insert.
在特定索引处插入
LogEntries.Insert(0, logEntry);
添加到 collection 的 "top"。
我认为这也可以避免排序。
你不希望 collection 变得很大,所以一旦你达到一个数字(比如 100 ),你就可以删除最旧的。
LogEntries.RemoveItem(100);
记得先检查你有超过 100 个条目,否则会出错。
您可能需要考虑对任何其他问题进行更全面的解释。我们只知道您告诉我们的内容,人们不太可能坐在那里思考您正在做的事情足够长的时间来意识到... "hey that's all the logs and the file could be quite big"。
使用StringBuilder
不会让你的代码变少。如果您想要更少的代码,请将 log4net.Info("bla bla");
放在 LogHelper 中,或者创建同时执行这两项工作的东西。
StringBuilder
在这里不相关,因为 Andy
说 Stringbuilder is only worth using if you're repeatedly appending text numerous times.
更多信息 -> String vs Stringbuilder
所以我有 WPf
应用程序和 Log4Net
所以每次我想添加 log
我只是这样添加:
log4net.Info("bla bla");
另外我想添加记录器 form
所以我创建了另一个 form
并且从我的主 form
我这样打开它:
LoggerForm loggerForm = new LoggerForm();
loggerForm.Show();
并创建日志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; }
}
和 LogHelper
将此 LogEvent
objects 保存在 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
插入我的列表。
收藏已更改:
每次将新 LogEvent
添加到我的 List
时,我都会将我的 ItemSource
更新到我的 ListView
:
ListView lvLogger;
private void LogEntries_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
lvLogger.ItemsSource = LogHelper.LogEntries;
}
好的,这些是我的问题:
每次我想创建新的
Log
我输入两次:log.Info("bla bla"); LogHelper.AddLog(Level.Info, "bla bla", $"MyClassName\MyMethodName");
所以你可以看到我在这里使用了两次字符串,所以我想知道使用
String.Builder
代替string
是否更好?
我还想提一下,我通过不同的线程更新我的日志。
当我的 Logger
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;
或者这是多余的?
1) Stringbuilder 只有在您多次重复附加文本时才值得使用。除非那是你正在做的,否则我只会使用一个字符串。 如果这是您正在做的事情,那么也许您不应该这样做。
看看你的代码,你似乎已经有了一个消息变量,所以我可能对这部分关于使用它两次的内容感到有点困惑。也许你不是在谈论消息。 我会将一个字符串传递给一个方法,并在你的两行代码中使用该变量。假设他们使用相同的方法。
log.Info(message);
LogHelper.AddLog(Level.Info, message, $"MyClassName\MyMethodName");
2) 这部分我看了好几遍,感觉很混乱。不过,作为一般原则,如果您从非私有成员订阅事件,那么您应该取消订阅该事件以避免任何内存泄漏。因此,如果 collection 由不同的 window 或其他东西更新,那么您应该取消订阅该处理程序,这样 window 的实例可以在您不再需要它时被垃圾收集.
根据评论中的进一步解释,很明显您可以按递减的日期时间对 collection 进行排序,然后在顶部查看最新的日志条目。这将避免 collection 完全更改事件处理程序。 collection视图排序: https://social.technet.microsoft.com/wiki/contents/articles/26673.wpf-collectionview-tips.aspx#Sorting
经过更多解释... 似乎文本文件是用于显示的。 我认为你应该完全忘记文本文件并使用 observablecollection 作为循环列表。
您正在对日志调用 add 方法:
LogEntries.Add(logEntry);
所做的是附加到 collection。您可以改为使用 insert.
在特定索引处插入LogEntries.Insert(0, logEntry);
添加到 collection 的 "top"。 我认为这也可以避免排序。 你不希望 collection 变得很大,所以一旦你达到一个数字(比如 100 ),你就可以删除最旧的。
LogEntries.RemoveItem(100);
记得先检查你有超过 100 个条目,否则会出错。
您可能需要考虑对任何其他问题进行更全面的解释。我们只知道您告诉我们的内容,人们不太可能坐在那里思考您正在做的事情足够长的时间来意识到... "hey that's all the logs and the file could be quite big"。
使用StringBuilder
不会让你的代码变少。如果您想要更少的代码,请将 log4net.Info("bla bla");
放在 LogHelper 中,或者创建同时执行这两项工作的东西。
StringBuilder
在这里不相关,因为 Andy
说 Stringbuilder is only worth using if you're repeatedly appending text numerous times.
更多信息 -> String vs Stringbuilder