我有一个带有一堆图像的ListBox(通过datatemplate完成)。通过设置项目来源创建图像:
<Image x:Name="ItemImage" Source="{Binding ImageUrl}"/>
然后使用listbox的Items.Clear()方法清除它们。使用列表框的Items.Add方法添加新图像。
然而,内存使用量开始上升和上升。它显示的是相同的300个左右的小图像,但内存似乎永远不会被释放。该应用程序开始使用大约40Megs,并迅速攀升至700Megs。如何释放所有这些图像正在使用的内存?
编辑:有一件事我忘了提及,图片(大小各约4-5k)正在通过网络加载。缓存是否以某种方式对此负责?显示12个图像会咀嚼大约10兆内存,大约是100X文件大小。
答案 0 :(得分:4)
除非您在加载图像时做任何异常操作(例如使用自制图像加载器或其他东西),否则当没有任何内容引用它时,GC应该为您擦除它们。
您是否继续在任何地方引用数据?请记住,事件和事件处理程序有时会“欺骗”垃圾收集器,使其认为对象仍在使用中:
MyObject obj = new MyObject();
obj.TheEvent += new EventHandler(MyHandler);
obj = null;
// Now you might think that obj is set for collection but it
// (probably - I don't have access to MS' .NET source code) isn't
// since we're still listening to events from it.
不确定这是否适用于你,但至少我会检查你是不是你。
此外,如果您有权访问分析器,例如AQTime或类似的,那么通过它运行代码可能会给您一些提示。
如果您从磁盘或嵌入到程序集中的资源加载图像,您也可以尝试查看它是否有任何区别。
答案 1 :(得分:4)
首先不要耗尽所有内存?
(注意:以下段落和代码均来自this answer。)
问题的一部分是它正在加载每个中的完整图像。您必须使用
IValueConverter
通过设置DecodePixelWidth
上的DecodePixelHeight
或BitmapImage
属性,以缩略图大小打开每个图片。这是我在我的一个项目中使用的一个例子......
class PathToThumbnailConverter : IValueConverter {
public int DecodeWidth {
get;
set;
}
public PathToThumbnailConverter() {
DecodeWidth = 200;
}
public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
var path = value as string;
if ( !string.IsNullOrEmpty( path ) ) {
FileInfo info = new FileInfo( path );
if ( info.Exists && info.Length > 0 ) {
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.DecodePixelWidth = DecodeWidth;
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.UriSource = new Uri( info.FullName );
bi.EndInit();
return bi;
}
}
return null;
}
public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
throw new NotImplementedException();
}
}
您可能还需要考虑IsAsync=True
中的Binding
,以便在后台线程中调用转换器。