不再需要BitmapImage后如何释放内存?

时间:2011-12-02 06:58:29

标签: wpf image memory bitmapimage

首先,我在BitmapImage上的Image控件上加载Window。 其次,我使用Image控件,然后关闭Window

我在一分钟内做了2-3次,而且我的记忆很快就会填满,因为当窗户关闭时,图像不会卸回。

那么如何手动从BitmapImage控件中卸载Image.Source以释放内存?

4 个答案:

答案 0 :(得分:24)

我相信您正在寻找的解决方案是http://www.ridgesolutions.ie/index.php/2012/02/03/net-wpf-bitmapimage-file-locking/。就我而言,我试图在创建文件后找到删除文件的方法,但它似乎是两个问题的解决方案。

没有释放内存:

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

释放内存,并允许删除文件:

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

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

或者,也可以冻结BitmapImage:

bitmap.Freeze();

答案 1 :(得分:3)

在我的情况下,似乎位图缓存是个问题。我之前加载了这样的位图:

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;

以相同的方式连续替换image.Source只是建立内存,手动强制垃圾收集并没有真正帮助。

相反,禁用缓存并让它使用流(需要让流保持打开状态直到显示图像)与手动垃圾收集配对,消除了内存构建。

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;
}

通过这种方式,我可以循环播放大量图像(如Windows Photo Viewer),并且内存保持不变。请注意,实际渲染图像后,流不必保持打开状态。

答案 2 :(得分:0)

您可以将对象设置为null,以便不再引用BitmapImage对象。 在这种情况下,GC应该负责释放资源。 您可以致电GC.Collect,但如果经常使用会影响效果。

答案 3 :(得分:-1)

您可以在窗口Dispose()事件中的图片上调用Closed。我认为使用不同的缓存选项也可以优化内存占用。

编辑:

您无法调用Dispose(),而是可以考虑使用BitmapCacheOption.None。图像将直接从磁盘读取,而不是缓存在内存中。

相关问题