首先,我将
BitmapImage
加载到位于 Image
上的 Window
控件中。
然后我使用 Image
控件,然后关闭 Window
。
我在一分钟内执行 2-3 次,我的内存很快就被填满,因为当窗口关闭时,由于某种原因图像不会从内存中卸载。
那么如何从
BitmapImage
控制手动卸载 Image.Source
以释放 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();
也可以冻结位图图像:
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
,但如果使用过于频繁,可能会影响性能。
您可以在窗口的
Dispose()
事件中对图像调用 Closed
。我认为也可以使用不同的缓存选项来优化内存占用。
编辑:
你不能调用Dispose(),相反,你可以考虑
BitmapCacheOption.None
。图像将直接从磁盘读取,不会缓存在内存中。