How to free the memory after the BitmapImage is no longer needed?

半腔热情 提交于 2020-01-08 21:39:33

问题


First, I load a BitmapImage on the Image control on the Window. Second, I work with the Image control and then close the Window.

I do it 2-3 times in a minute and my memory fills up very quickly because the images do not unload back when the window is closed.

So how to unload BitmapImage from Image.Source control manually to free the memory?


回答1:


I believe the solution you are looking for is at http://www.ridgesolutions.ie/index.php/2012/02/03/net-wpf-bitmapimage-file-locking/. In my case, I was trying to find a way to delete the file after it was created, but it appears to be a solution to both issues.

Doesn't free up memory:

var bitmap = new BitmapImage(new Uri(imageFilePath));

Frees up memory, and allows file to be deleted:

var bitmap = new BitmapImage(); 
var stream = File.OpenRead(imageFilePath);

bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
stream.Close();
stream.Dispose();

Optionally, also freeze the BitmapImage:

bitmap.Freeze();



回答2:


In my situation it seems that the bitmap caching was the issue. I was previously loading bitmaps like this:

Bitmap bitmap = new Bitmap();

using(var stream = new FileStream(...))
{
    bitmap.BeginInit();
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.StreamSource = stream;
    bitmap.EndInit();
}

bitmap.Freeze();
image.Source = bitmap;

Continuously replacing image.Source the same way just built up memory, manually forcing garbage collection wasn't really helping.

Instead, disabling the caching and having it use the stream (requires leaving the stream open until the image is displayed) paired with manual garbage collection eliminated memory build up for me.

Stream mediaStream;

void DisposeMediaStream()
{
    if (mediaStream != null)
    {
        mediaStream.Close();
        mediaStream.Dispose();
        mediaStream = null;
        GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
    }
}

void Update()
{
    DisposeMediaStream();

    var bitmap = new BitmapImage();
    mediaStream = new FileStream(...);

    bitmap.BeginInit();
    bitmap.CacheOption = BitmapCacheOption.None;
    bitmap.StreamSource = mediaStream;
    bitmap.EndInit();

    bitmap.Freeze();
    ControlImage.Source = bitmap;
}

This way I can cycle through tons of images (like Windows Photo Viewer) and memory stays low. Note that the stream does not have to stay open once the image has actually rendered.




回答3:


You can set the object to null, so that the BitmapImage object is no longer referenced. In this situation, the GC should take care of freeing up resources. You can call GC.Collect but it can affect performance if used too often.




回答4:


You can call Dispose() on the images in the window's Closed event. I think it may also be possible to optimise your memory footprint using different caching options.

Edit:

You can't call Dispose(), instead, you might consider BitmapCacheOption.None. The image will be read directly from disk and not cached in memory.



来源:https://stackoverflow.com/questions/8352787/how-to-free-the-memory-after-the-bitmapimage-is-no-longer-needed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!