Утечка памяти WPF с использованием RenderTargetBitmap?

Меня немного сбивает с толку утечка памяти в моем коде WPF. Я визуализирую некоторую трехмерную геометрию для нескольких RenderTargetBitmaps, а затем визуализирую каждую из них в большом главном RenderTargetBitmap. Но когда я это делаю, я получаю утечку памяти, из-за которой мое приложение вылетает через минуту или две.

Я воспроизвел ошибку в следующем упрощенном фрагменте кода.

   private void timer1_Tick(object sender, EventArgs e) {
       // if first time, create final stitch bitmap and set UI image source
       if (stitch == null) {
           stitch = new RenderTargetBitmap(1280, 480, 96, 96, PixelFormats.Pbgra32);
           myImage.Source = stitch;
       }

       // create visual and render to img1
       Rect rect = new Rect(new Point(160, 100), new Size(320, 80));
       DrawingVisual dvis = new DrawingVisual();
       using (DrawingContext dc = dvis.RenderOpen()) {
           dc.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null, rect); 
       }
       RenderTargetBitmap img1 = new RenderTargetBitmap(640, 480, 96, 96, PixelFormats.Pbgra32);
       img1.Render(dvis);

       // create visual and render to final stitch
       DrawingVisual vis = new DrawingVisual();
       using (DrawingContext dc = vis.RenderOpen()) {
           dc.DrawImage(img1, new Rect(0, 0, 640, 480));
       }

       stitch.Clear();
       stitch.Render(vis);
   }   

Может ли кто-нибудь увидеть что-нибудь очевидное, что здесь идет не так? Почему этот код имел вопиющую утечку памяти?


person TrespassersW    schedule 09.02.2013    source источник
comment
Думаю, я тоже это вижу. Какое исключение у вас есть?   -  person Gleno    schedule 04.04.2013


Ответы (1)


если вы отслеживаете поведение класса RenderTargetBitmap с помощью монитора ресурсов, вы можете видеть, что каждый раз при вызове этого класса вы теряете 500 КБ памяти. мой ответ на ваш вопрос: не используйте RenderTargetBitmap class так много раз

Вы даже не можете освободить используемую память RenderTargetBitmap.

Если вам действительно нужно использовать класс RenderTargetBitmap, просто добавьте эти строки в конец вашего кода.

GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()

Это может решить вашу проблему:

private void timer1_Tick(object sender, EventArgs e) {
       // if first time, create final stitch bitmap and set UI image source
       if (stitch == null) {
           stitch = new RenderTargetBitmap(1280, 480, 96, 96, PixelFormats.Pbgra32);
           myImage.Source = stitch;
       }

       // create visual and render to img1
       Rect rect = new Rect(new Point(160, 100), new Size(320, 80));
       DrawingVisual dvis = new DrawingVisual();
       using (DrawingContext dc = dvis.RenderOpen()) {
           dc.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null, rect); 
       }
       RenderTargetBitmap img1 = new RenderTargetBitmap(640, 480, 96, 96, PixelFormats.Pbgra32);
       img1.Render(dvis);

       // create visual and render to final stitch
       DrawingVisual vis = new DrawingVisual();
       using (DrawingContext dc = vis.RenderOpen()) {
           dc.DrawImage(img1, new Rect(0, 0, 640, 480));
       }

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
       stitch.Clear();
       stitch.Render(vis);
}   
person GiGatR00n    schedule 21.07.2014
comment
Ух ты. Обратный путь сюда. Мы давно совсем отказались от WPF, поэтому решение больше не актуально. Но спасибо, что нашли время ответить. Я пометил ваш ответ как принятый. Я полагаю, что другим решением было бы просто постоянно сохранять и повторно использовать одни и те же RenderTargetBitmaps. Теперь это кажется очевидным. Приятно знать, что они не очень хорошо убирают за собой. Итак, спасибо, что нашли время ответить. - person TrespassersW; 23.07.2014