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



首先,我将BitmapImage加载到位于Window上的Image控件中。然后我使用Image控件,然后关闭Window

我在一分钟内做2-3次,我的内存很快就填满了,因为当窗口关闭时,由于某种原因图像不能从内存中卸载。

那么我如何从Image.Source控制手动卸载BitmapImage以释放RAM?

我相信你正在寻找的解决方案是在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();

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

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照片查看器)和内存保持低。请注意,一旦图像实际呈现,流不必保持打开状态。

您可以将对象设置为null,以便不再引用BitmapImage对象。在这种情况下,GC应该负责释放资源。你可以调用GC.Collect,但是如果太频繁的话会影响性能。

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

编辑:

你不能调用Dispose(),相反,你可以考虑BitmapCacheOption.None。映像将直接从磁盘读取,而不是缓存在内存中。

最新更新