我正在开发一个应用程序,它将保持正在运行的工作索引。
我可以在工作会话结束时写一次,但我不想冒着丢失数据的风险。因此,每次用户进行新条目或更正时,我都会重写为磁盘(XML)。
private void WriteIndexFile()
{
XmlDocument IndexDoc
// Build document here
XmlTextWriter tw = new XmlTextWriter(_filePath, Encoding.UTF8);
tw.Formatting = Formatting.Indented;
IndexDoc.Save(tw);
}
可以快速连续触发写入。如果发生这种情况,它会在先前的写入完成之前尝试打开文件进行写入。 (虽然这不正常,但我认为文件可能会被另一个程序打开使用。)
如何检查文件是否可以重写?
编辑以澄清:这是自动化实验室数据收集系统的一部分。用户将单击按钮以捕获数据(保存在单独的文件中),并识别数据包所针对的子任务。通常,点击之间的间隔为3-10分钟。
如果他们犯了错误,他们需要能够返回并更正错误,因此这不是仅限附加用法。
最后,文件将由其他自动化工具读取并由人工手动读取。 (XML / XSLT)
大小将受到限制,因为每个工作会话(工人班次或更少)将生成新的索引文件。
进一步的问题:由于压倒性的共识是不使用XML并以仅附加模式写入,我如何解决返回和纠正先前条目的要求?
我正在考虑使用“脏”标志,并在设置标志后和关闭工作会话后保存几分钟。如果在那段时间内发生了多次编辑,则只有一次写入 - 没有更快的用户 - 如果保存失败,也会有重试/取消对话框。想法?
答案 0 :(得分:4)
在您的情况下,XML是一个糟糕的选择,因为必须在结束标记之前插入新内容。使用Text istead并只需打开要追加的文件并在文件末尾写下新内容,请参阅How to: Open and Append to a Log File。
您还可以查看一个简单的日志框架,如log4net,并使用它而不是自己处理低级文件。
答案 1 :(得分:1)
如果您只想要所有操作的简单日志,那么XML可能是错误的选择,因为如果不重写整个文件很难附加到XML文档,随着文件的增长,这将变得越来越慢。 / p>
我建议改为File.AppendText
甚至更好:在应用程序的生命周期内保持文件打开并使用WriteLine
。
(哦,正如其他人所指出的,你需要lock
来确保一次只有一个线程写入文件。即使使用这个解决方案,这仍然是正确的。)
还有一些日志框架已经解决了这个问题,比如log4net。您是否考虑过使用现有的日志记录框架而不是自己编辑?
答案 2 :(得分:0)
我有一个使用System.Collections.Queue
的记录器。基本上它等到排队等待然后尝试写它。在编写可能很慢的项目时,可以将更多项目添加到队列中。
这也有助于对邮件进行分组,而不是试图跟上。它在一个单独的线程上运行。
private AutoResetEvent ResetEvent { get; set; }
LogMessage(string fullMessage)
{
this.logQueue.Enqueue(fullMessage);
// Trigger the Reset Event to send the
this.ResetEvent.Set();
}
private void ProcessQueueMessages()
{
while (this.Running)
{
// This will process all the items in the queue.
while (this.logQueue.Count > 0)
{
// This method will just log the top item on the queue
this.LogQueueItem();
}
// Once the queue is empty will wait for a
// another message to queueed before running again.
// Rather than sleeping and checking if the queue is full,
// saves from doing a System.Threading.Thread.Sleep(1000); stuff
this.ResetEvent.WaitOne();
}
}
我处理写入失败但没有出列,直到它写入文件没有错误。然后我继续尝试,直到它最终可以写。这节省了我,因为有人在此过程中从我们的某个应用程序中删除了权限。关闭我们的应用程序后返回权限,我们没有丢失一个日志声明。
答案 3 :(得分:0)
考虑使用平面文本文件。我有一个使用XML日志编写的进程......这是一个糟糕的选择。您无法在运行时写出状态,而无需不断重写文件以确保标记正确无误。如果它是写入文件的平面条目,你可以有一个自动时间轴,可以给你详细说明发生了什么,而不试图弄清楚它是否是XML编写器/标签集爆炸了你不必担心你的日志膨胀了。
答案 4 :(得分:0)
我同意其他人建议您避免使用XML。另外,我建议你有一个组件(一个“监视器”)负责所有文件的访问。该组件将负责处理多个并发请求并使磁盘写入一个接一个地发生。