Memory increase when using RenderTargetBitmap on 32 bit png

HerMei 1 Reputation point
2021-02-24T07:27:31.847+00:00

We are encountering a strange problem when creating preview screenshots of UserControls within our application. If a user control contains a 32 bit png image, the memory used for the image creation is not released afterwards, while there is apparently no problem when only 24 bit images are used.

The UserControls are created by users and are loaded into our application. Within the application, at some time we are creating preview images of those controls using RenderTargetBitmap.Render() and a PngBitmapEncoder + FileStream to save it as an image. The memory increase happens when calling the Render method and it is never released.

This behaviour can be reproduced in a sample application:

  • 2 UserControls are created consisting of only 1 image, on the first encoded with a 32 bit png, on the second with a 24 bit png. This image is a simple image with the dimension 2500x2500px, only containing colored noise, no transparency.

Control 1:

<UserControl x:Class="WpfApp1.UserControl1">
  <StackPanel >
    <Image Source="pack://application:,,,/images/noise3x32.png" />
  </StackPanel>
</UserControl>

Control 2:

<UserControl x:Class="WpfApp1.UserControl2">
  <StackPanel >
    <Image Source="pack://application:,,,/images/noise3x24.png" />
  </StackPanel>
</UserControl>
  • A content control is placed on the main window
    <StackPanel>
        <ContentControl x:Name="UCContentControl" ></ContentControl>
    </StackPanel>
    
  • The UC is loaded into the content control
        UserControl1 uc1 = new UserControl1();
        UCContentControl.Content = uc1;
    
  • A render target bitmap is created and render is called
        var uc = UCContentControl.Content as FrameworkElement;
    
        RenderTargetBitmap rtb = new RenderTargetBitmap(1888, 968, 96d, 96d, PixelFormats.Pbgra32);
        rtb.Render(uc);
    

The full demo app is available at github

When executing this sample, we notice the following:

Application memory usage

Loading the 32 bit image UserControl takes memory for the UC itself, as expected. Creating a RenderTargetBitmap and calling render increases the memory consumption further. This memory is consumed as long as the Control exists. Unloading the Control releases the memory. However, this behaviour can only be reproduced with 32 bit png images, doing the same with 24 bit png images causes no further memory increase.

Unfortunately, we can't simply unload our controls in our actual application. So, this poses the questions:

  • How can the memory consumed upon calling RenderTargetBitmap.Render be freed without unloading the control?
  • What exactly keeps the memory from being released? Does the UserControl hold any references?
  • Why does this only happen with 32 bit PNGs?
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,678 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,289 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
767 questions
{count} votes