Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Known issus: WPF Image memory leak when remove image from visual tree #2397

Open
lindexi opened this issue Jan 5, 2020 · 2 comments
Open

Known issus: WPF Image memory leak when remove image from visual tree #2397

lindexi opened this issue Jan 5, 2020 · 2 comments
Milestone

Comments

@lindexi
Copy link
Contributor

@lindexi lindexi commented Jan 5, 2020

  • .NET Core Version: 3.1.100
  • Windows version: 18363
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes
  • Is this bug related specifically to tooling in Visual Studio No

Problem description:

The image source will memory leak when we remove the image from visual tree before we set the image source as null

Step:

  1. Set the image source
  2. Add image in the VisualTree and wait the image show
  3. Remove image from the visual tree and then set the image source as null

And you can find the image source object never free

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Remove the current Image control from the  visual tree and set source is null when click button.
            // Then new a image control and add source to the RenderTargetBitmap object and show it.
            // You can see the gc never delete the RenderTargetBitmap object that make  memory leak.

            var oldBorder = RootGrid.Children.OfType<Border>().LastOrDefault();
            if (oldBorder != null)
            {
                var oldImage = (Image)oldBorder.Child;

                // In order to solve it , you should set the image.Source is null and use UpdateLayout.
                // The below code can solve it.
                // oldImage.Source = null;
                // oldImage.UpdateLayout();

                // Remove the current Image control from the  visual tree.
                RootGrid.Children.Remove(oldBorder);
                oldImage.Source = null;
                Borders.Add(oldBorder);
            }

            var bitmap = new RenderTargetBitmap(1024, 1024, 96, 96, PixelFormats.Default);

            var image = new Image { Source = bitmap };
            var border = new Border { Child = image };
            RootGrid.Children.Add(border);

            // In order to facilitate changes in memory, after each operation will be garbage collection
            GC.Collect();
        }

        public readonly List<Border> Borders = new List<Border>();

Actual behavior:

The Image memory leak

Expected behavior:

The image source object can be free

Minimal repro:

https://github.com/dotnet-campus/wpf-issues/tree/master/ImageMemoryLeakDotNetCore

@lindexi

This comment has been minimized.

Copy link
Contributor Author

@lindexi lindexi commented Jan 5, 2020

How to solve it?

In order to solve it , you should set the image.Source is null and use UpdateLayout.

The below code can solve it.

            oldImage.Source = null;
            oldImage.UpdateLayout();
@lindexi

This comment has been minimized.

Copy link
Contributor Author

@lindexi lindexi commented Jan 5, 2020

Why the image will memory leak?

Because the Image use RenderData class to storage the image source object and the UIElement._drawingContent will reference the RenderData.

The image will never re-render when we remove the image from the visual tree and the RenderData will never update.

Why we set the image source as null and then update layout can solve?

Because the image source is null and the update layout will call render to update the _drawingContent to the new RenderData which does not storage the image source object (or it stroage a null object)

@gomathip02 gomathip02 added this to the 5.0 milestone Jan 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.