2013-04-02 78 views
0

我有一個使用線程運行一系列插件的程序。在此過程中,它將插件的運行時間寫入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.爲什麼我的XDocument保存不完整的文件?

我進行了一些跟蹤語句,結果發現,在這之前的時間,服務失敗,約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; 
    } 

的問題是,一個或多個插件的不正確處理錯誤,從而導致它不返回任何響應並使程序崩潰。

+2

豈不是可以張貼的代碼和輸入的一些例子嗎? –

+1

從你的故事中得知你的服務崩潰了?如果是這樣的話,你很難期望所有對象都能正確處理並將其更改寫入磁盤。 – Virtlink

+0

我會嘗試添加一些。掛在那裏。 – ijb109

回答

1

讀取XML文件,而不分析整個事情,它加載到內存中,你可以使用XmlReader class。然後編寫XML文件,您可以使用XmlWriter class。在各自的MSDN頁面上有一些例子。

但是,你將失去LINQ的所有優點,它的工作原理不同頗有幾分。在處理僅在磁盤上的XML文件時,實際上沒有辦法將LINQ和XDocument的好處結合起來。

然後當你的服務崩潰,你XmlWriter可能仍然沒有得到安置,不沖水的緩衝區寫入磁盤並留下你仍然不完整的XML文件。您應該解決導致服務崩潰的錯誤。

相關問題