I created a .NET Windows service that performs certain actions and generates reports. These reports are XPS documents that I save in a specific directory.
Being familiar with WPF, the way I decided to create reports was to instantiate System.Windows.Documents.FixedDocument by adding FixedPage objects with content as needed.
My problem is that the use of service memory increases and increases over time as it starts up.
At first, I strictly went through my code, ensuring that all disposable objects were deleted, etc., and other obvious candidates for a memory leak, but there were still problems. Then I used the CLR Profiler to learn more about using the service in the memory service.
I found that since the service generates these FixedDocument reports and saves them as XPS files, all of the various user interface elements associated with FixedDocument objects ( Dispatcher , FixedPage , UIElementCollection , Visual , etc.) remain in memory.
This is not like I am doing the same in my WPF applications, and therefore I suspect it has something to do with the WPF UI manager model used outside of the WPF application.
How can I "manage" my FixedDocument objects FixedDocument using them in such a service (or outside of a WPF application in general)?
======== EDIT ==========
OK, I found that the memory leak is not specifically related to creating / populating FixedDocument. If I do this, but actually never save it to disk as XPS, there will be no memory leak. So my problem should be to save the XPS file.
Here is my code:
var paginator = myFixedDocument.DocumentPaginator; var xpsDocument = new XpsDocument(filePath, FileAccess.Write); var documentWriter = XpsDocument.CreateXpsDocumentWriter(xpsDocument); documentWriter.Write(paginator); xpsDocument.Close();
What I tried:
- Manual garbage collection
- Call
UpdateLayout() on each myFixedDocument page before getting its paginator (as indicated in the answer below). I also tried passing myFixedDocument directly to Write() ie, not paginator - Entering these lines of code in your own thread and manually closing dispatchers
Still out of luck.
=========== WORKAROUND ===========
By highlighting the above code in your own AppDomain, using the general method shown in the example at http://msdn.microsoft.com/en-us/library/system.appdomain.aspx , a memory leak no longer affects my service (I say "more doesnβt affect "because it is still happening, but when the AppDomain is unloaded, all leaked resources are unloaded with it).
I would still like to see a real solution.
(Due to the fact that for interested users, the use of a separate AppDomain caused a memory leak in the PDFSharp component, which I used to turn certain XPS files into PDF files. It turns out that PDFSharp uses a global font cache, which in normal circumstances does not work. I increased the size cache, but after using these AppDomains the cache increased and increased. I edited the PDFSharp source code so that I could manually clear FontDescriptorStock and FontDataStock, solving the problem.)
========== SOLUTION ===========
See my answer below for a final decision.