Ho creato un servizio Windows .NET che esegue determinate azioni e genera report. Questi rapporti sono documenti XPS che salvo in una determinata directory.Il salvataggio di un documento fisso in un file XPS causa una perdita di memoria
Conoscendo WPF, il modo in cui ho scelto di creare i report è creare un'istanza di System.Windows.Documents.FixedDocument
, aggiungendo gli oggetti FixedPage
con i contenuti necessari.
Il mio problema è che l'utilizzo della memoria di servizio aumenta e aumenta nel tempo durante l'esecuzione.
In un primo momento, ho esaminato il mio codice rigorosamente, assicurandomi che tutti gli oggetti monouso fossero stati smaltiti, ecc. E altri ovvi candidati alla perdita di memoria, ma avevo ancora il problema. Ho quindi utilizzato il CLR Profiler per esaminare l'utilizzo della memoria del Servizio in dettaglio.
ho scoperto che il servizio genera questi FixedDocument
rapporti, e le salva come file XPS, tutti i vari elementi dell'interfaccia utente associati FixedDocument
oggetti (Dispatcher
, FixedPage
, UIElementCollection
, Visual
, ecc) si alloggia in memoria.
Questo non sembra accadere quando faccio la stessa cosa nelle mie app WPF, e quindi la mia impressione è che abbia qualcosa a che fare con il modello del Dispatcher UI WPF utilizzato al di fuori di un'app WPF.
Come posso "smaltire" i miei oggetti FixedDocument
quando li uso in un servizio come questo (o al di fuori di un'applicazione WPF in generale)?
======== EDIT =========
OK, ho trovato che la mia perdita di memoria non è specificamente a che fare con la creazione/compilazione di un FixedDocument. Se lo faccio, ma in realtà non lo salvi su disco come XPS, la perdita di memoria non si verifica. Quindi, il mio problema deve essere legato al salvataggio come file XPS.
Ecco il mio codice:
var paginator = myFixedDocument.DocumentPaginator;
var xpsDocument = new XpsDocument(filePath, FileAccess.Write);
var documentWriter = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
documentWriter.Write(paginator);
xpsDocument.Close();
Quello che ho provato:
- garbage collection Manuale
- Calling
UpdateLayout()
su ogni pagina delmyFixedDocument
prima di ottenerlo di paginator (come suggerito nella risposta di seguito) - Ho anche provato a passaremyFixedDocument
direttamente inWrite()
ovvero non l'impaginatore - Inserimento di quelle righe di codice nella propria discussione e chiusura manuale Dispatcher
Ancora senza fortuna.
========== SOLUZIONE ==========
Isolando il codice sopra in proprio AppDomain utilizzando il metodo generale illustrato nell'esempio in http://msdn.microsoft.com/en-us/library/system.appdomain.aspx, la la perdita di memoria non influisce più sul mio servizio (dico "non influisce più" perché succede ancora, ma quando l'AppDomain viene scaricato, tutte le risorse trapelate vengono scaricate con esso).
Sarei ancora curioso di vedere una soluzione reale.
(Su una nota correlata, per gli interessati, l'utilizzo di un AppDomain separato ha provocato una perdita di memoria nel componente PDFSharp che stavo usando per trasformare determinati file XPS in file PDF. Si scopre che PDFSharp utilizza una cache di carattere globale che in circostanze normali non cresce in modo significativo. Ma la cache è stata in crescita e in crescita dopo l'utilizzo di questi AppDomain. ho modificato il codice sorgente PDFsharp mi consentano di cancellare manualmente la FontDescriptorStock e FontDataStock, risolvendo il problema.)
===== ===== SOLUZIONE ==========
Vedere la mia risposta qui sotto per la soluzione finale.
controllo quasi esatto duplicato: http://stackoverflow.com/questions/5883779/how-to-dispose-a-fixeddocument – Nat
La risposta non confermato a quella la domanda è di forzare la garbage collection di GC. Anche se non ritengo questa una soluzione accettabile, l'ho provato comunque e non ha funzionato per me. Grazie comunque. – Ross