我创建了一个 .NET Windows 服务,它执行某些操作并生成报告。这些报告是我保存在某个目录中的 XPS 文档。
熟悉 WPF,我选择创建报告的方式是实例化 a System.Windows.Documents.FixedDocument
,根据需要添加FixedPage
具有内容的对象。
我的问题是服务内存使用量随着时间的推移不断上升。
起初,我严格检查了我的代码,确保所有一次性对象都被释放,等等,以及其他明显的内存泄漏候选,但仍然存在问题。然后我使用 CLR Profiler 详细查看了 Service 的内存使用情况。
我发现当服务生成这些报告并将它们保存为 XPS 文件时,与对象(、、、、等)FixedDocument
关联的所有各种 UI 元素都保留在内存中。FixedDocument
Dispatcher
FixedPage
UIElementCollection
Visual
当我在我的 WPF 应用程序中做同样的事情时,这似乎不会发生,所以我的直觉是它与在 WPF 应用程序之外使用的 WPF UI Dispatcher 模型有关。
FixedDocument
在这样的服务中(或一般在 WPF 应用程序之外)使用对象时,如何“处置”我的对象?
======== 编辑 =========
好的,我发现我的内存泄漏与创建/填充 FixedDocument 无关。如果我这样做了,但实际上并没有将它作为 XPS 保存到磁盘,则不会发生内存泄漏。所以,我的问题一定与另存为 XPS 文件有关。
这是我的代码:
var paginator = myFixedDocument.DocumentPaginator;
var xpsDocument = new XpsDocument(filePath, FileAccess.Write);
var documentWriter = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
documentWriter.Write(paginator);
xpsDocument.Close();
我试过的:
- 手动垃圾收集
- 在获取它的分页器之前调用
UpdateLayout()
每一页myFixedDocument
(如下面的答案中所建议) - 我也尝试过myFixedDocument
直接传递给Write()
ie 而不是分页器 - 将这些代码行放在自己的线程中并手动关闭调度程序
仍然没有运气。
========== 解决方法 ==========
通过使用http://msdn.microsoft.com/en-us/library/system.appdomain.aspx示例中所示的通用方法将上述代码隔离到它自己的 AppDomain 中,内存泄漏不再影响我的服务(我说“不再影响”,因为它仍然会发生,但是当 AppDomain 被卸载时,所有泄漏的资源都会被卸载)。
我仍然渴望看到一个真正的解决方案。
(在相关说明中,对于那些感兴趣的人,使用单独的 AppDomain 会导致我用来将某些 XPS 文件转换为 PDF 文件的 PDFSharp 组件中的内存泄漏。原来 PDFSharp 使用在正常情况下不会增长的全局字体缓存显着。但是使用这些 AppDomain 后缓存越来越大。我编辑了 PDFSharp 源代码,使我能够手动清除 FontDescriptorStock 和 FontDataStock,解决了这个问题。)
========== 解决方案 ==========
请参阅下面的答案以获取最终解决方案。