2012-06-13 19 views
5

He escrito un código que carga un documento XML utilizando un objeto XmlDocument para contar sus nodos. Aquí está el método:C#: el método close de Xml.Load (archivo)

XmlDocument xml = new XmlDocument(); 
xml.Load(textBox1.Text); 
XmlNodeList nodes = xml.SelectNodes("//File"); 
foreach (XmlNode node in nodes) 
{ 
    number_of_childs++; 
} 

El problema que estoy enfrentando es, al importar un archivo de gran tamaño, se toma como 700 MB de RAM. Si luego trato de hacer alguna operación en el archivo, o incluso leer de él para mostrar sus datos en un ListView, la aplicación toma como 2 GB de RAM. Entonces, me preguntaba, ¿hay algún método que cierre el XmlDocument y libere su memoria, liberando la RAM? Es como si olvidara eliminar su contenido de la memoria.

Respuesta

12

No. La clase XmlDocument no implementa IDisposable, por lo que no hay forma de obligarlo a liberar sus recursos a voluntad. Si realmente necesita liberar inmediatamente a la memoria utilizada por XmlDocument, la única manera de hacerlo sería hacer lo siguiente:

colector
nodes = null; 
xml = null; 
GC.Collect(); 

La basura trabaja en un hilo separado, por lo que todavía no puede suceder inmediatamente. Para forzar la recolección de basura que se produzca de forma sincrónica, antes de la ejecución de su código continua, también debe llamar WaitForPendingFinalizers, tales como:

nodes = null; 
xml = null; 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 

XmlDocument siempre carga todo el documento en la memoria a la vez. Si simplemente desea iterar a través de los nodos en el documento como una secuencia, solo cargando bit a bit, para eso es la clase XmlReader. Sin embargo, pierde mucha funcionalidad de esa manera. Por ejemplo, no hay forma de seleccionar nodos a través de XPath, como lo haría en su ejemplo. Con XmlReader, debe escribir su propia lógica para determinar en qué parte del documento se encuentra y si coincide con lo que está buscando.

+0

Gracias por esa información, pero no funcionó, he aplicado su fragmento de código pero todavía se reserva la misma cantidad de memoria. –

+0

@ R.Vector ver mi edición. –

+0

Sí funcionó, pero el segundo paso de la aplicación es leer cada nodo y escribirlo en una vista de lista, por lo que todavía existe problema, pero ¿qué ocurre si puedo leer cada nodo del xml y liberarlo de la memoria cuando estaba almacenados con éxito en algún lugar <<< de esa manera sería mejor para la gestión de la memoria. –

2

Si no tiene que manipular el XML, simplemente lea el XML usando XMLReader, que es de una sola dirección y el más rápido, con menos memoria con un funcionamiento intenso.

1

No es necesario establecer su objeto como nulo. El GC debería poder indicar si el documento no se está utilizando más por sí mismo. Esto sucederá automáticamente ya que se necesita memoria, pero si desea borrarla inmediatamente, llame al GC.Collect(). Ver this thread para mayor discusión.

+1

Estoy de acuerdo en que normalmente no es una gran preocupación y el GC eventualmente liberará la memoria por sí mismo, pero si va a llamar al recolector de basura manualmente, debe establecer la variable como nula antes de llamar a GC.Collect, de lo contrario, se seguirá haciendo referencia al objeto y no se recopilará. –

+0

@Steven Doggart, su afirmación solo es cierta en las versiones de depuración. En las compilaciones de Release, no es necesario establecer en null: el GC es lo suficientemente inteligente como para ver que ya no se hace referencia a él sin establecerlo como nulo. Ver http://stackoverflow.com/questions/5545288/garbage-collection-of-orphaned-objects-tree-nodes-works-for-the-release-exe por ejemplo. –

+0

@MattSmith Eso es sorprendente e interesante. ¿Eso se debe a que la compilación Release, por defecto, incluye optimizaciones adicionales que establecerían automáticamente la variable a 'null' tan pronto como ya no se use, o algo así? –

Cuestiones relacionadas