XDocument + IEnumerable вызывает исключение нехватки памяти в System.Xml.Linq.dll

В основном у меня есть программа, которая при запуске загружает список файлов (как FileInfo ) и для каждого файла в списке загружает XML-документ (как XDocument ).

Затем программа считывает данные из него в контейнерный класс (сохраняя как IEnumerables ), после чего XDocument выходит за пределы области.

Программа затем экспортирует данные из класса контейнера в базу данных. После экспорта контейнерный класс выходит из области видимости, однако сборщик мусора не очищает контейнерный класс, который, поскольку его сохранение как IEnumerable , похоже, приводит к XDocument остается в памяти (не уверен, является ли это причиной, но диспетчер задач показывает, что память из XDocument не освобождается).

Поскольку программа перебирает несколько файлов в цикле, в конечном итоге программа выдает исключение нехватки памяти. Чтобы смягчить этот эффект, я использовал

System.GC.Collect(); 

для принудительного запуска сборщика мусора после того, как контейнер выходит за пределы области видимости. это работает, но мои вопросы:

  • Правильно ли это? (Принуждение к запуску сборщика мусора кажется немного странным)
  • Есть ли лучший способ убедиться, что память XDocument удаляется?
  • Может быть другая причина, кроме IEnumerable , что память документа не освобождается?

Спасибо.


Изменить: Примеры кода:

  • Класс контейнера:

     общедоступный IEnumerable  CustomClassOne {get; установлен; } 

    • Верно ли это? (Принуждение к запуску сборщика мусора кажется немного странным)
    • Есть ли лучший способ убедиться, что память XDocument удаляется?
    • Может быть другая причина, кроме IEnumerable , что память документа не освобождается?

    Спасибо.


    Изменить: Примеры кода:

    • Класс контейнера:

       общедоступный IEnumerable  CustomClassOne {get; установлен; } 

      • Верно ли это? (Принуждение к запуску сборщика мусора кажется немного странным)
      • Есть ли лучший способ убедиться, что память XDocument удаляется?
      • Может быть другая причина, кроме IEnumerable , что память документа не освобождается?

      Спасибо.


      Изменить: Примеры кода:

      • Класс контейнера:

         общедоступный IEnumerable  CustomClassOne {get; установлен; }
        общедоступный IEnumerable  CustomClassTwo {получить; установлен; }
        общедоступный IEnumerable  CustomClassThree {получить; установлен; }
        ...
        общедоступный IEnumerable  CustomClassNine {получить; установлен; }
        
      • Пользовательский класс:

         public long VariableOne {get; установлен; }
        public int VariableTwo {получить; установлен; }
        общедоступные DateTime VariableThree {получить; установлен; }
        ...
        

        Во всяком случае, это действительно основные структуры. Пользовательские классы заполняются через класс контейнера из XML-документа. Сами заполненные структуры используют очень мало памяти.

      Контейнерный класс заполняется из одного XML-документа, выходит за пределы области видимости, затем загружается следующий документ, например,

          public static void ExportAll(IEnumerable<FileInfo> files)
          {
              foreach (FileInfo file in files)
              {
                  ExportFile(file);
                  //Temporary to clear memory
                  System.GC.Collect();
              }
          }
          private static void ExportFile(FileInfo file)
          {
              ContainerClass containerClass = Reader.ReadXMLDocument(file);
              ExportContainerClass(containerClass);
              //Export simply dumps the data from the container class into a database
              //Container Class (and any passed container classes) goes out of scope at end of export
          }
      
          public static ContainerClass ReadXMLDocument(FileInfo fileToRead)
          {
              XDocument document = GetXDocument(fileToRead);
              var containerClass = new ContainerClass();
      
              //ForEach customClass in containerClass
              //Read all data for customClass from XDocument
      
              return containerClass;
          }
      

      Забыл упомянуть этот бит (не уверен, соответствует ли он), файлы могут быть сжаты как .gz, поэтому у меня есть метод GetXDocument () для его загрузки

          private static XDocument GetXDocument(FileInfo fileToRead)
          {
              XDocument document;
      
              using (FileStream fileStream = new FileStream(fileToRead.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
              {
                  if (String.Equals(fileToRead.Extension, ".gz", StringComparison.OrdinalIgnoreCase))
                  {
                      using (GZipStream zipStream = new GZipStream(fileStream, CompressionMode.Decompress))
                      {
                          document = XDocument.Load(zipStream);
                      }
                  }
                  else
                  {
                      document = XDocument.Load(fileStream);
                  }
                  return document;
              }
          }
      

      Надеюсь, этой информации достаточно. Спасибо

      Редактировать: System.GC.Collect () не работает 100% времени, иногда кажется, что программа сохраняет XDocument , у кого-то есть идея, почему это может быть?

      public static ContainerClass ReadXMLDocument(FileInfo fileToRead)
      {
          XDocument document = GetXDocument(fileToRead);
          var containerClass = new ContainerClass();
      
          //ForEach customClass in containerClass
          //Read all data for customClass from XDocument
      
          containerClass.CustomClassOne = document.Descendants(ElementName)
              .DescendantsAndSelf(ElementChildName)
              .Select(a => ExtractDetails(a));
      
          return containerClass;
      }
      
      private static CustomClassOne ExtractDetails(XElement itemElement)
      {
          var customClassOne = new CustomClassOne();
          customClassOne.VariableOne = Int64.Parse(itemElement.Attribute("id").Value.Substring(4));
          customClassOne.VariableTwo = int.Parse(itemElement.Element(osgb + "version").Value);
          customClassOne.VariableThree = DateTime.ParseExact(itemElement.Element(osgb + "versionDate").Value,
                  "yyyy-MM-dd", CultureInfo.InvariantCulture);
          return customClassOne;
      }
      
13
задан Manatherin 11 January 2011 в 10:08
поделиться