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