首先,我将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
。映像将直接从磁盘读取,而不是缓存在内存中。