Home > database >  Memory 'leak' with MemoryStream and BitmapCacheOption.OnLoad
Memory 'leak' with MemoryStream and BitmapCacheOption.OnLoad

Time:10-12

I have to get a BitmapSource from an Image and for this I use an extension method like this:

public static BitmapSource ToBitmapSource(this Image image)
{
    LogEx.FunctionEnter();

    if (image == null)
        throw new ArgumentNullException("image");

    BitmapImage bitmapImage = null;
    using (MemoryStream memory = new MemoryStream())
    {
        image.Save(memory, ImageFormat.Jpeg);
        memory.Position = 0;
        bitmapImage = new BitmapImage();
        bitmapImage.BeginInit();
        bitmapImage.StreamSource = memory;
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.EndInit();
    }

    LogEx.FunctionLeave("Rendered image as BitmapSource");
    return bitmapImage;
}

If I now release the handle of this and dispose the original Image it stays in the memory, even after calling the GC by hand multiple times. I tested to use files instead of streams with this little piece of code:

string filename = $"c:\\temp\\{page}.jpg";
if (File.Exists(filename))
{
    File.Delete(filename);
}
_highResPageImages[page].Save(filename, ImageFormat.Jpeg);
Uri uri = new Uri(filename);
BitmapImage source = new BitmapImage();
source.BeginInit();
source.UriSource = uri;
source.CacheOption = BitmapCacheOption.OnLoad;
source.EndInit();
Document.PageImage = source;
// Ducument.PageImage = _highResPageImages[page].ToBitmapSource();

And even if there is also an onl oad, it gets disposed when the handle is released. So it must be something with the MemoryStream. But what? I tried this WrapperStream I found somewhere else and to use the Freeze() Method of BitmapImage, but both to no a avail. The problem is, that I cannot cache the images on the drive of the customer (even if it wouldn't cost a huge amount of time to do so) and I get the Image from another DLL, so I cannot change it beforehand. Has someone else an idea?

Edit: I use WPF and the value of the handle is being used in a Binding for display. Maybe that matters somehow. Or that I use BitmapSource in the Binding and handle and not the original BitmapImage.

CodePudding user response:

Try this in ToBitmapSource:

...
bitmapImage.StreamSource = null;
return bitmapImage
  • Related