Утечка визуальной памяти WPF

#c# #wpf #printing

#c# #wpf #печать

Вопрос:

У меня возникла небольшая проблема при использовании PrintDialog.PrintVisual , поскольку, похоже, это вызывает утечку памяти.

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

Вызов печати

 public void PrintDocument()
{
   PrintUserControl printControl = new PrintUserControl();
   printControl.Print();
}
  

Пользовательский элемент управления печатью

 public class PrintUserControl
{
    public PrintUserControl()
    {
       InitializeComponent();
    }

    public void Print()
    {
        const double width = 5.8 * 96;
        const double height = 8.3 * 96;

        this.Measure(new Size(width, height));
        this.Arrange(new Rect(new Size(width, height)));
        this.UpdateLayout();

        var dlg = new PrintDialog();

        PageMediaSize pageMedia = new PageMediaSize(PageMediaSizeName.ISOA5);
        dlg.PrintTicket.PageMediaSize = pageMedia;
        dlg.PrintVisual(this, "FooDocument");
    }
}
  

Я профилировал это приложение, и при вызове PrintUserControl.Print метода возникает утечка памяти, многие экземпляры LayoutEventList ListItem и ConditionalWeakTable . Если я закомментирую PrintUserControl.Print метод, то утечек не будет, но, очевидно, ничего не печатается.

Разве я не избавляюсь от того, что должен?

Комментарии:

1. Проверьте объекты, которые вы используете, на наличие методов удаления. Если они у них есть, вызовите их. Кроме того, помните, что объекты НЕ исчезают, когда они выходят за пределы области видимости, только при запуске GC, что может произойти через некоторое время.

2. К сожалению, ни один из объектов не является одноразовым. Я использую ANTS performance profiler и отслеживаю IDisposable объекты, но они не отображаются.

3. Сообщает ли это вам, что готово для GC? Я думаю, что Sysinternals Process Explorer сделает это, если нет.

4. Двумя «классами», которые являются Gen2 и растут, являются LayoutEventList ListItem и ConditionalWeakTable

5. Изменил это на ответ, так как комментарий стал слишком длинным…

Ответ №1:

Итак, они были должным образом очищены, но GC не запустился и не запустится, пока не решит, что это необходимо. (Обычно это происходит, когда на компьютере не хватает памяти.)

В принципе, так оно и есть .NET работает, и в целом, как работают языки, собирающие мусор.

Преимущество в том, что вам не нужно беспокоиться о том, следует ли использовать Free или delete, или об утечках памяти, когда вы забываете использовать либо то, либо другое; недостатком является то, что ваш процесс использует больше памяти, пока сборщик не приступит к очистке.

Он не будет запускаться до тех пор, пока не возникнет необходимость в очистке, поскольку в противном случае Он забирает ресурсы (процессор и т. Д.) Из вашего приложения, Когда они действительно не нужны в другом месте. Это произойдет только при соблюдении некоторых условий, таких как нехватка доступной системной памяти. Я считаю, что обстоятельства, при которых GC решает выполнить, являются «деталями реализации», и на них не следует полагаться, поскольку они будут меняться между ними.СЕТЕВЫЕ версии.

Разумный вариант — это из MSDN. Вы также можете выполнить поиск по «недетерминированной финализации», в которой было задействовано несколько человек, когда .NET был в оригинальной бета-версии iuts.

Комментарии:

1. По прошествии времени моя машина с 2 ГБ оперативной памяти использует 2 ГБ, так что это не значит, что GC не вызывается. Используя ANTS profiler, я могу вручную вызвать полный GC, и элементы все еще там.

2. ОК. Должно быть, я неправильно понял, что вам показывал ANTS — извините. Что такое LayoutEventList? Поиск этого не дает ничего особенного. Где вы это используете? Где это определено?