2013-04-02 2 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, чтобы он не повредил фактический файл, если что-то происходит во время работы?

EDIT: Вот пример кода, который использует 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, и это будет работать совсем по-другому. Невозможно объединить преимущества LINQ и XDocument при работе с файлами XML только на диске.

И после сбоя службы ваш XmlWriter может по-прежнему не удаляться, а не удалять его буферы на диск и оставлять вас с неполным XML-файлом. Вы должны решить проблему, которая приводит к сбою службы.

Смежные вопросы