Ich habe einen .NET Windows-Dienst erstellt, der bestimmte Aktionen ausführt und Berichte generiert. Diese Berichte sind XPS-Dokumente, die ich in einem bestimmten Verzeichnis speichern kann.
Wenn ich mit WPF vertraut bin, habe ich die Art und Weise gewählt, wie ich die Berichte erstellen möchte, indem ich ein System.Windows.Documents.FixedDocument
instanziiere und FixedPage
-Objekte mit dem Inhalt nach Bedarf hinzufüge.
Mein Problem ist, dass die Speicherbelegung des Dienstes im Laufe der Zeit hoch und runter geht.
Zuerst habe ich meinen Code gründlich durchgesehen, um sicherzustellen, dass alle verfügbaren Objekte entsorgt wurden, und andere offensichtliche Speicherleck-Kandidaten, aber ich hatte immer noch das Problem. Ich habe dann den CLR Profiler verwendet, um die Speichernutzung des Dienstes im Detail zu betrachten.
Ich habe festgestellt, dass, während der Dienst diese FixedDocument
-Berichte generiert und sie als XPS-Dateien speichert, alle verschiedenen UI-Elemente, die FixedDocument
-Objekten zugeordnet sind ( Dispatcher
, FixedPage
, UIElementCollection
, Visual
usw.) bleiben in Erinnerung.
Dies scheint nicht der Fall zu sein, wenn ich in meinen WPF-Apps dasselbe mache. Daher ist meine Vermutung, dass es etwas mit dem WPF-UI-Dispatcher-Modell zu tun hat, das außerhalb einer WPF-App verwendet wird.
Wie kann ich meine FixedDocument
-Objekte "entsorgen", wenn Sie sie in einem Dienst wie diesem verwenden (oder außerhalb einer WPF-App im Allgemeinen)?
======== EDIT =========
OK, ich habe festgestellt, dass mein Speicherverlust nicht speziell mit dem Erstellen / Füllen eines FixedDocuments zu tun hat. Wenn ich dies tue, aber nicht wirklich als XPS auf die Festplatte speichere, passiert das Speicherleck nicht. Also, mein Problem muss mit dem Speichern als XPS-Datei zu tun haben.
Hier ist mein Code:
%Vor%Was ich versucht habe:
UpdateLayout()
auf jeder Seite von myFixedDocument
vor dem Paginator (wie in der Antwort unten vorgeschlagen) - Ich habe auch versucht, myFixedDocument
direkt in Write()
, d. h. nicht den Paginator Immer noch kein Glück.
========== Abhilfe ==========
Indem Sie den obigen Code mithilfe der allgemeinen Methode, die im Beispiel unter Ссылка dargestellt wird, in seine eigene AppDomain einbinden , der Speicherverlust wirkt sich nicht mehr auf meinen Dienst aus (ich sage "betrifft das nicht mehr", weil es immer noch passiert, aber wenn die AppDomain entladen wird, werden alle ausgelaufenen Ressourcen damit entladen).
Ich wäre immer noch scharf darauf, eine echte Lösung zu sehen.
(Bei einer diesbezüglichen Anmerkung verursachte die Verwendung einer separaten Anwendungsdomäne einen Speicherverlust in der PDFSharp-Komponente, die ich verwendete, um bestimmte XPS-Dateien in PDF-Dateien umzuwandeln.) PDFsharp verwendet einen globalen Zeichensatzcache, der unter normalen Umständen nicht funktioniert Der Cache wuchs und wuchs, nachdem ich diese AppDomains verwendet habe. Ich habe den PDFSharp-Quellcode bearbeitet, damit ich manuell FontDataStock und FontDataStock löschen konnte, um das Problem zu lösen.)
========== LÖSUNG ===========
Siehe meine Antwort unten für die endgültige Lösung.
Ich habe schließlich eine Antwort gefunden, die aus zwei Teilen besteht.
Erstens, nachdem ich mein XPS-Dokument auf dem Datenträger gespeichert und das XpsDocument
geschlossen / entsorgt habe, führe ich die folgende Codezeile aus:
Dies löscht alle Dispatcher
Objekte, die im Speicher hängen.
Während das obige die meisten Speicherprobleme aussortiert, bemerkte ich, dass es noch FixedPage-Objekte zusammen mit anderen noch im Speicher befindlichen UI-Objekten gab. Manuelles Löschen meines FixedDcounts scheint sie los zu werden:
%Vor%Tags und Links wpf memory-leaks fixeddocument dispatcher xpsdocument