Memory Leak When Asynchronously Loading BitmapSource Images

I have several images that I upload to a ListBox in my WPF application. I originally used GDI to resize images (originals take up too much memory). This was fine, except that they took about 400 ms per image. Not so good. Therefore, in search of another solution, I found a method that uses TransformedBitmap (which inherits from BitmapSource). β€œIt's great,” I thought, β€œI can use it. Besides the fact that I'm now losing memory leaks ...

I load images asynchronously using BackgroundWorker, for example:

BitmapSource bs = ImageUtils.ResizeBitmapSource(ImageUtils.GetImageSource(photo.FullName)); //BitmapSource bs = ImageUtils.GetImageSource(photo.FullName); bs.Freeze(); this.dispatcher.Invoke(new Action(() => { photo.Source = bs; })); 

GetImageSource simply gets the bitmap from the path and then converts it to BitmapSource.

Here is the code snippet for ResizeBitmapSource:

 const int thumbnailSize = 200; int width; int height; if (bs.Width > bs.Height) { width = thumbnailSize; height = (int)(bs.Height * thumbnailSize / bs.Width); } else { height = thumbnailSize; width = (int)(bs.Width * thumbnailSize / bs.Height); } BitmapSource tbBitmap = new TransformedBitmap(bs, new ScaleTransform(width / bs.Width, height / bs.Height, 0, 0)); return tbBitmap; 

This code is essentially code from: http://rongchaua.net/blog/c-wpf-fast-image-resize/

Any ideas what could cause the leak?

edit: Here is the code for GetImageSource requested

 using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (var bmp = Image.FromStream(stream, false, false)) { // Use WPF to resize var bitmapSource = ConvertBitmapToBitmapSource(bmp); bitmapSource = ResizeBitmapSource(bitmapSource); return bitmapSource; } } 
+4
source share
2 answers

I think you misunderstood how TransformedBitmap works. It contains a link to the original bitmap and converts it to memory. Perhaps you can encode the converted bitmap into a memory stream and read it back. I’m not sure how fast it would be, but then you can’t resist a full-sized bitmap.

I found this blog post in which WriteableBitmap with TransformedBitmap was returned as the source. WriteableBitmap will copy the pixel data to the memory buffer in the initializer, so it does not actually hold the reference to the TransformedBitmap or full-size image.

+4
source

Assuming that looking at your code, you might need to get rid of the bitmap obtained by calling ImageUtils.GetImageSource (photo.FullName).

I also noted on the blog that you indicated that the author added an update (March 11) to insert a using statement to prevent memory leaks.

+1
source

Source: https://habr.com/ru/post/1303846/


All Articles