为什么我的XDocument保存了一个不完整的文件
本文关键字:一个 文件 XDocument 我的 保存 为什么 | 更新日期: 2023-09-27 18:06:58
我有一个使用线程运行一系列插件的程序。在这个过程中,它将插件的运行时写入到一个XDocument中,以便程序知道自上次运行该插件以来已经过了多长时间。不过我有个问题。大约每天一次(在不可预测的时间),当我加载XDocument时,我得到以下错误:[04/01/2013 08:17:10.083] Unexpected end of file has occurred. The following elements are not closed: Database, DatabaseList. Line 4043, position 1.
我运行了一些跟踪语句,发现在此之前,服务失败了,大约有44个插件要运行,这显然导致XDocument在没有写入文件末尾的情况下关闭。它写入和读取硬盘上的XML文件,但是它在内存中对XDocument执行所有操作,因为我使用Linq对数据执行复杂的操作。
有人知道为什么会这样吗?如何加载XDocument,以便在运行过程中发生某些事情时它不会破坏实际文件?
编辑:下面是使用XDocument
(命名为XDoc
)的代码示例:
private void RunPlugin(object oQueuedPlugin)
{
PluginState oPluginState = (PluginState)oQueuedPlugin;
PluginResponse oResponse = new PluginResponse();
XElement xPlugin;
lock (xDoc)
{
xPlugin = GetPluginNode(oPluginState.ClientFusionDatabase.Name, oPluginState.Plugin.Name);
}
if (xPlugin == null)
{
API.Log.Write("ActivityTrace.ShowXMLLog", "XML for " + oPluginState.ClientFusionDatabase.Name + " was null.");
XElement NewPlugin = new XElement("Plugin",
new XAttribute("PluginName", oPluginState.Plugin.Name),
new XAttribute("Running", "true"),
new XAttribute("LastStart", DateTime.Now.ToString()),
new XAttribute("LastSuccess", ""),
new XAttribute("LastExitStatus",""));
lock (xDoc)
{
var Location = from database in xDoc.Root.Elements("Database")
where database.Attribute("DatabaseName").Value == oPluginState.ClientFusionDatabase.Name
select database;
Location.FirstOrDefault().Add(NewPlugin);
xDoc.Save(XmlLogFilePath);
}
oResponse = oPluginState.Plugin.Run(oPluginState.ClientFusionDatabase);
if (oResponse == null)
{
API.Log.Write("ActivityTrace.ShowNullReturnLog", oPluginState.ClientFusionDatabase.Name + "- " + oPluginState.Plugin.Name + " returned null.");
}
lock (xDoc)
{
NewPlugin.Attribute("Running").Value = "false";
NewPlugin.Attribute("LastExitStatus").Value = oResponse.ResponseType.ToString();
if (oResponse.ResponseType == PluginResponseTypes.Success || oResponse.ResponseType == PluginResponseTypes.Warning)
NewPlugin.Attribute("LastSuccess").Value = DateTime.Now.ToString();
xDoc.Save(XmlLogFilePath);
}
API.Log.Write("ActivityTrace.ShowXMLLog","Completed " + oPluginState.ClientFusionDatabase.Name + "- " + oPluginState.Plugin.Name + " with XML " + NewPlugin.ToString());
API.Log.Write(oPluginState.Plugin.Name, "(" + oPluginState.ClientFusionDatabase.Connection.Database + " = " + (oResponse.ResponseType + ") ").PadRight(9) + "EXIT MESSAGE: " + (string.IsNullOrEmpty(oResponse.Message) ? "None" : oResponse.Message));
}
else
{
DateTime dLastRun = (DateTime)xPlugin.Attribute("LastStart");
bool bRunning = (bool)xPlugin.Attribute("Running");
if ((DateTime.Now - dLastRun) > oPluginState.Plugin.Interval && !bRunning)
{
lock (xDoc)
{
xPlugin.Attribute("LastStart").Value = DateTime.Now.ToString();
xPlugin.Attribute("Running").Value = "true";
xDoc.Save(XmlLogFilePath);
}
oResponse = oPluginState.Plugin.Run(oPluginState.ClientFusionDatabase);
lock (xDoc)
{
xPlugin.Attribute("Running").Value = "false";
xPlugin.Attribute("LastExitStatus").Value = oResponse.ResponseType.ToString();
if (oResponse.ResponseType == PluginResponseTypes.Success || oResponse.ResponseType == PluginResponseTypes.Warning)
xPlugin.Attribute("LastSuccess").Value = DateTime.Now.ToString();
xDoc.Save(XmlLogFilePath);
}
API.Log.Write(oPluginState.Plugin.Name, "(" + oPluginState.ClientFusionDatabase.Connection.Database + " = " + (oResponse.ResponseType + ") ").PadRight(9) + "EXIT MESSAGE: " + (string.IsNullOrEmpty(oResponse.Message) ? "None" : oResponse.Message));
}
else if (bRunning)
API.Log.Write(oPluginState.Plugin.Name, "(" + oPluginState.ClientFusionDatabase.Connection.Database + " = " + ("SKIPPED) ").PadRight(9) + "REASON: Plugin already running");
}
oPluginState.Complete = true;
}
问题是一个或多个插件没有正确处理错误,这导致它没有返回任何响应并导致程序崩溃。
要读取XML文件而不解析整个内容并将其加载到内存中,您可以使用XmlReader
类。然后要编写XML文件,可以使用XmlWriter
类。在相应的MSDN页面上有一些示例。
然而,你将失去LINQ的所有好处,它的工作方式也有很大的不同。如果只在磁盘上处理XML文件,确实没有办法将LINQ和XDocument
的优点结合起来。
然后,当您的服务崩溃时,您的XmlWriter
可能仍然没有被处理,没有将其缓冲区刷新到磁盘,并且仍然留下不完整的XML文件。你应该解决导致服务崩溃的bug。