我正在开发一个Web应用程序的日志记录系统,它使用Task.Factory.StartNew(()=> iLogEventSave())在将字典对象发送到我的日志记录对象之前将其记录在字典对象中。记录器似乎工作正常,但在某些情况下某些事件没有正确保存,因此我使用lock()语句来纠正问题。这似乎可以解决问题,但是通过这样做,应用程序的性能大大降低了。如何在不等待任务完成工作的情况下进行UI /页面渲染?
以下是代码
private static readonly object Locker = new object();
public void iLogEventSave(object state)
{
XmlDocument doc = new XmlDocument();
IDictionary<string, string> EventDetails = (IDictionary<string, string>)state;
string logFile = "";
if(ConfigurationManager.AppSettings["Log_File_Path"].ToString() =="")
{
logFile = HttpRuntime.AppDomainAppPath + "Logs\\" + DateTime.Now.ToString("yyyy_MM_dd") + ".txt";
}
else
{
logFile = ConfigurationManager.AppSettings["Log_File_Path"].ToString() + DateTime.Now.ToString("yyyy_MM_dd") + ".txt";
}
lock (Locker)
{
if (File.Exists(logFile))
{
doc.Load(logFile);
}
else
{
var root = doc.CreateElement("Log");
doc.AppendChild(root);
}
var el = (XmlElement)doc.DocumentElement.AppendChild(doc.CreateElement("Event"));
foreach (KeyValuePair<string, string> item in EventDetails)
{
XmlElement Desc = doc.CreateElement("Details");
Desc.SetAttribute(item.Key.ToString(), item.Value);
el.AppendChild(Desc);
}
doc.Save(logFile);
}
}
答案 0 :(得分:1)
如果您的日志在异步执行时没有保存多个事件,则会出现未处理的未处理错误。考虑到你正在使用一个文件,我会说它失败了,因为两个线程正在竞争访问同一个日志文件,第一个抓住它的线程锁定了另一个。这就是你的锁现在可以工作的原因,它可以防止其他线程试图抓取文件。
但是,记录到文件意味着您已经有效地将自己限制在一个线程中并随着它的增长处理整个文件。您必须加载越来越多,追加越来越多,锁定线程意味着the more threads are waiting to log the events, the higher your overhead。所有这些肯定会导致性能下降。
我可以建议使用数据库表来记录事件吗?文件I / O非常昂贵,资源和时间。在这些情况下,数据库具有较少的开销和更好的吞吐量。