Сохранение FixedDocument в файл XPS вызывает утечку памяти

Я создал .NET Windows Service, который выполняет определенные действия и генерирует отчеты. Эти отчеты представляют собой документы XPS, которые я сохраняю в определенном каталоге.

Поскольку я знаком с WPF, я выбрал способ создания отчетов - создать экземпляр System.Windows.Documents.FixedDocument , добавив при необходимости объекты FixedPage с содержимым.

Моя проблема в том, что использование служебной памяти постоянно увеличивается и увеличивается по мере его работы.

Сначала я тщательно изучил свой код, убедившись, что все одноразовые объекты удалены и т. Д., И другие очевидные кандидаты на утечку памяти, но проблема все еще оставалась. Затем я использовал профилировщик CLR, чтобы подробно изучить использование памяти Службой.

Я обнаружил, что по мере того, как служба генерирует эти отчеты FixedDocument и сохраняет их в виде файлов XPS, все различные элементы пользовательского интерфейса, связанные с объектами FixedDocument ( Dispatcher ] , FixedPage , UIElementCollection , Visual и т. Д.) Остаются в памяти.

Похоже, этого не происходит, когда я делаю то же самое в своих приложениях WPF, и поэтому я догадываюсь, что это как-то связано с моделью диспетчера пользовательского интерфейса WPF, используемой вне приложения WPF.

Как я могу "избавиться" от моих объектов FixedDocument при использовании их в такой службе (или вне приложения WPF в целом)?

======== EDIT == =======

Хорошо, я обнаружил, что моя утечка памяти не связана конкретно с созданием / заполнением 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 () , т.е. не в пагинатор
  • , помещая эти строки кода в отдельный поток и отключение диспетчеров вручную

По-прежнему не повезло.

========== ВОЗМОЖНОЕ РЕШЕНИЕ ==========

Путем изолирования приведенного выше кода в его собственном домене приложения с помощью общего метода, показанного в примере по адресу http: //msdn.microsoft.com/en-us/library/system.appdomain.aspx, утечка памяти больше не влияет на мою службу (я говорю «больше не влияет», потому что это все еще происходит, но когда домен приложения выгружается , с ним выгружаются все утекшие ресурсы).

Мне все еще хотелось бы увидеть реальное решение.

(Кстати, для тех, кто заинтересован, использование отдельного домена приложений вызвало утечку памяти в компоненте PDFSharp, который я использовал для преобразования определенных файлов XPS в файлы PDF.Оказывается, PDFSharp использует глобальный кеш шрифтов, который в нормальных условиях существенно не увеличивается. Но после использования этих доменов приложений кеш рос и разрастался. Я отредактировал исходный код PDFSharp, чтобы я мог вручную очистить FontDescriptorStock и FontDataStock, решив проблему.)

========== РЕШЕНИЕ ==========

См. Мой ответ ниже для окончательного решения.

10
задан Ross 11 January 2012 в 23:03
поделиться