He creado un servicio Windows .NET que realiza ciertas acciones y genera informes. Estos informes son documentos XPS que guardo en un directorio determinado.Guardar un FixedDocument en un archivo XPS provoca una pérdida de memoria
Al estar familiarizado con WPF, la forma en que he elegido crear los informes es instanciar un System.Windows.Documents.FixedDocument
, agregando FixedPage
objetos con el contenido requerido.
Mi problema es que el uso de la memoria del servicio aumenta y aumenta con el tiempo a medida que se ejecuta.
Al principio, revisé mi código rigurosamente, asegurándome de que todos los objetos desechables estaban dispuestos, etc., y otros candidatos obvios a la pérdida de memoria, pero aún así tenía el problema. Luego utilicé CLR Profiler para ver el uso de la memoria del Servicio en detalle.
He encontrado que a medida que el servicio genera estos informes FixedDocument
, y las guarda como archivos XPS, todos los diversos elementos de interfaz de usuario asociados con objetos (FixedDocument
Dispatcher
, FixedPage
, UIElementCollection
, Visual
, etc) están alojados en la memoria.
Esto no parece suceder cuando hago lo mismo en mis aplicaciones WPF, por lo que mi corazonada es que tiene algo que ver con el modelo WPF UI Dispatcher que se utiliza fuera de una aplicación WPF.
¿Cómo puedo "desechar" mis objetos FixedDocument
cuando los utilizo en un servicio como este (o fuera de una aplicación WPF en general)?
======== ========= EDITAR
OK, he encontrado que mi pérdida de memoria no es específicamente que ver con la creación/llenar una FixedDocument. Si lo hago, pero en realidad nunca lo guardo en el disco como un XPS, la pérdida de memoria no ocurre. Entonces, mi problema tiene que ver con guardar como archivo XPS.
Aquí está mi código:
var paginator = myFixedDocument.DocumentPaginator;
var xpsDocument = new XpsDocument(filePath, FileAccess.Write);
var documentWriter = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
documentWriter.Write(paginator);
xpsDocument.Close();
Lo que he intentado:
- recolección manual de basura
- Calling
UpdateLayout()
en cada página delmyFixedDocument
antes de conseguir que del paginador (como se sugiere en la respuesta a continuación) - También he intentado pasarmyFixedDocument
directamente enWrite()
es decir, no el paginador - Poner esas líneas de código en su propio hilo y cerrar manualmente Despachadores
Todavía no hubo suerte.
Solución ========== ==========
Al aislar el código anterior en su propio dominio de aplicación usando el método general que se muestra en el ejemplo en http://msdn.microsoft.com/en-us/library/system.appdomain.aspx, la la pérdida de memoria ya no afecta mi servicio (digo "ya no me afecta" porque todavía sucede, pero cuando el AppDomain está descargado, todos los recursos filtrados se descargan con él).
Todavía estaría ansioso por ver una solución real.
(En una nota relacionada, para los interesados, el uso de un dominio de aplicación separado causó una pérdida de memoria en el componente PDFSharp que estaba utilizando para convertir ciertos archivos XPS en archivos PDF. Resulta que PDFSharp utiliza un caché de fuente global que en circunstancias normales no crece significativamente. Pero la caché estaba creciendo y creciendo después de usar estos dominios de aplicación. edité el código fuente PDFsharp que me permita borrar manualmente el FontDescriptorStock y FontDataStock, la solución del problema.)
===== ===== SOLUCIÓN ==========
Consulte mi respuesta a continuación para la solución final.
cheque casi exacta duplicado: http://stackoverflow.com/questions/5883779/how-to-dispose-a-fixeddocument – Nat
La respuesta no confirmada a ese La pregunta es forzar la recolección de basura GC. Si bien no considero que esto sea una solución aceptable, lo intenté de todos modos y no funcionó para mí. Gracias de cualquier manera. – Ross