WPF:我应该在日志中使用字符串ob StringBuilder吗
因此,我有WPF:我应该在日志中使用字符串ob StringBuilder吗,wpf,multithreading,log4net,Wpf,Multithreading,Log4net,因此,我有WPf应用程序和Log4Net,所以每次我想添加log时,我都是这样添加的: log4net.Info("bla bla"); LoggerForm loggerForm = new LoggerForm(); loggerForm.Show(); 此外,我想添加记录器表单,因此我创建了另一个表单,并从我的主表单以以下方式打开它: log4net.Info("bla bla"); LoggerForm loggerForm = new LoggerForm(); loggerFo
WPf
应用程序和Log4Net
,所以每次我想添加log
时,我都是这样添加的:
log4net.Info("bla bla");
LoggerForm loggerForm = new LoggerForm();
loggerForm.Show();
此外,我想添加记录器表单
,因此我创建了另一个表单
,并从我的主表单
以以下方式打开它:
log4net.Info("bla bla");
LoggerForm loggerForm = new LoggerForm();
loggerForm.Show();
并创建日志对象
:
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
对象,并将每个LogEvent
添加到此列表中:
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);
}));
}
}
}
此行:
LogHelper.AddLogToList = true;
指示已打开我的日志窗体
,以便我可以将我的LogEvent
i插入我的列表
收藏更改:
LogHelper.AddLogToList = true;
每次新的LogEvent
添加到我的列表中
我都会将我的ItemSource
更新到我的列表视图中
:
ListView lvLogger;
private void LogEntries_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
lvLogger.ItemsSource = LogHelper.LogEntries;
}
好的,这就是我的问题:
LogHelper.AddLogToList = true;
每次我想创建新的Log
时,我都会键入两次:
log.Info("bla bla");
LogHelper.AddLog(Level.Info, "bla bla", $"MyClassName\\MyMethodName");
正如您所看到的,我在这里使用了两次字符串,所以我想知道是否最好使用string.Builder
而不是string
我还想提到,我通过不同的线程更新日志
当我的记录器窗体
关闭时,我注册到其关闭事件
并清除我的日志事件
列表:
private void MetroWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
LogHelper.AddLogToList = false;
LogHelper.LogEntries.Clear();
}
所以我这里的问题是,我是否应该在这里注销我的日志条目\u CollectionChanged
事件:
LogHelper.LogEntries.CollectionChanged-=LogEntries\u CollectionChanged
或者这是多余的?1)只有在多次重复追加文本时,Stringbuilder才值得使用。除非你这么做,否则我就用一根绳子。
如果这是你正在做的,那么也许你不应该这样做
看看你的代码,你似乎已经有了一个消息变量,所以我可能对这部分关于两次使用它的内容有点困惑。也许你不是在谈论信息。
我会将一个字符串传递给一个方法,并在那里的两行代码中使用该变量。假设他们采用相同的方法
log.Info(message);
LogHelper.AddLog(Level.Info, message, $"MyClassName\\MyMethodName");
2) 这一部分我读了好几遍,都弄糊涂了。不过,作为一项一般原则,如果您订阅的事件不是私人成员,那么您应该取消订阅该事件,以避免任何内存泄漏。因此,如果集合是由不同的窗口或其他对象更新的,那么您应该取消订阅该处理程序,以便在不再需要该窗口的实例时可以对其进行垃圾收集
从注释中的进一步解释可以看出,您可能只需按减少的日期时间对集合进行排序,并在顶部查看最新的日志条目。这将完全避免collectionchanged事件处理程序。collectionview的排序:
经过更多的解释。。。
文本文件似乎是用于显示的。
我认为您应该完全忘记文本文件,使用observablecollection作为循环列表
您正在对日志项调用add方法:
LogEntries.Add(logEntry);
这样做的目的是将其附加到集合中。您可以改为使用insert在特定索引处插入
LogEntries.Insert(0, logEntry);
这将增加收藏的“顶部”。
我认为这也可以避免排序。
你不想让这个收藏变得庞大,所以一旦你点击了一个数字(比如100),你就可以删除最古老的
LogEntries.RemoveItem(100);
记得先检查你有超过100个条目,否则会出错
你可能想考虑更进一步的问题。我们只知道你告诉我们什么,人们不太可能长时间坐在那里思考你在做什么而意识到。。。“嘿,这就是所有的日志,文件可能相当大” 使用StringBuilder
不会减少代码。如果您想要更少的代码,请放入log4net.Info(“bla-bla”)代码>在LogHelper中,或创建同时执行两个作业的内容
StringBuilder
在这里不相关,因为Andy
说StringBuilder只有在多次重复添加文本时才值得使用。
更多信息->我忘了提到log.Info(例如)是我的txt文件日志,而我的LogHelper.AddLog是我的logger表单中的ListView,只有当用户希望打开此logger表单并以更方便的方式查看它,然后查看txt文件时,才可以在文件中添加新字符串。将整个文件保存在内存中听起来不是一个好计划。如果我理解你的意思,你有什么建议?只要把我的字符串放进一个变量,这个字符串就会传递到我的两个日志对象中?(顺便说一句,我的列表最多有1000个条目,当我的列表大约有1000个条目时,我会开始删除第一个条目)我不明白为什么你想要一个txt文件和一个日志文件,但是的,我只会将相同的参数传递给两个方法。因为我的txt文件可以容纳许多条目,我有高达10MB的文件,其中包含不断增长的文件和最多3个文件,如果我在LisyView中放入如此多的条目,我的记忆就会崩溃。我的问题是(将它们放在同一个函数中)我的log4net配置为同时向我显示类名和方法([%logger/%method])因此,如果我将其放在一个函数中,所有条目将来自同一位置,而不是来自原始位置。顺便说一句,因为StringBuilder只有在多次重复添加文本时才有效-创建静态StringBuilder并将我的所有日志消息放在该对象中是否更好?否,创建静态StringBuilder
也不会有任何改善,要从包装的类中收集正确的方法名,可以在此处进行检查