Как извлечь из класса NameTable для уменьшения утечки памяти XmlReader? - PullRequest
1 голос
/ 14 июня 2011

В этой статье говорится, что использование XMLReader может привести к утечке строковой памяти.(просто найдите «утечка памяти», чтобы найти абзац).В нем говорится, что одно из смягчений:

Одним из смягчающих воздействий для этого является получение из класса NameTable и применение квоты на максимальный размер.(Нет никакого способа предотвратить использование NameTable или переключить NameTable, когда он заполнен)

Та же проблема и смягчение также упоминаются здесь .Мой вопрос заключается в том, как я «наследуюсь от класса NameTable и применяю квоту максимального размера», как предлагают статьи?

Ответы [ 2 ]

0 голосов
/ 14 июня 2011

Я не знаю, если это единственный способ сделать это, но то, что делается в WCF (где у вас уже есть такая квота, MaxNameTableCharCount ), - это создание подкласса System.Xml.XmlReader, либо путем реализации функций считывателя самостоятельно (не весело), ​​либо путем делегирования внутреннему считывателю (более вероятно).Вы можете переопределить виртуальное свойство NameTable , чтобы вернуть собственную реализацию XmlNameTable .Эта реализация может просто делегировать вызовы к исходной таблице имен, но применяет некоторую квоту для ее размера.

Если XML, который вам нужно проанализировать, соответствует подмножеству, поддерживаемому читателями WCF (т.е. без инструкций обработки,нет ссылок на сущности, нет DTD), вы можете использовать читатель WCF напрямую (они могут использоваться вне служб). XmlDictionaryReader.CreateTextReader принимает параметр, который содержит квоты, которые должны быть применены к читателю, и один из них имеет дело именно с таблицей имен.

0 голосов
/ 14 июня 2011

Это не ответ на ваш вопрос, но он может помочь смягчить вашу "проблему утечки памяти в C #".

Используя шаблон RAII для C #, вы можете как распоряжаться неуправляемыми ресурсами, так и (когда объект выходит из области видимости) разрешить GC дозировать управляемые.

Код, который я использовал на работе, выглядит примерно так:

void ParseXmlString(string p_xmlString)
{
   using (var stringReader = new StringReader(p_xmlString))
   using (var xmlReader = XmlReader.Create(stringReader))
   {
      while (xmlReader.Read())
      {
         // etc.
      }
   }
}

Как вы можете видеть, переменная xmlReader ( и stringReader ) является локальной, создаваемой для каждой попытки анализа (*).

Это означает, что они будут собраны (**), и, таким образом, утечки виртуальной памяти предотвращены.

Глядя на класс XmlReader, я не вижу способа переопределить NameTable, поэтому я не вижу способа предложить альтернативную реализацию.

К сожалению.

(*) это не может соответствовать вашему проекту, но подходит моему, поэтому ...

(**) Надеюсь ... Вы никогда не знаете с GC, но тогда вы все равно можете попробовать System.GC.Collect() для этого

...