首先,我在BitmapImage
上的Image
控件上加载Window
。
其次,我使用Image
控件,然后关闭Window
。
我在一分钟内做了2-3次,而且我的记忆很快就会填满,因为当窗户关闭时,图像不会卸回。
那么如何手动从BitmapImage
控件中卸载Image.Source
以释放内存?
答案 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
。图像将直接从磁盘读取,而不是缓存在内存中。