在Listbox中处理WPF中的图像(内存泄漏)

我有一个ListBox,里面有一堆图像(通过datatemplate完成)。 通过设置项目来源创建图像:

 

然后使用列表框的Items.Clear()方法清除它们。 使用列表框的Items.Add方法添加新图像。

但是,内存使用量开始上升和上升。 它显示的是相同的300个左右的小图像,但内存似乎永远不会被释放。 该应用程序开始使用大约40Megs,并迅速攀升至700Megs。 如何释放所有这些图像正在使用的内存?

编辑 :有一件事我忘了提到,图像(大小各约4-5k)正在通过网络加载。 缓存是否以某种方式对此负责? 显示12个图像会咀嚼大约10兆内存,大约是100X文件大小。

除非你在加载图像时做任何不寻常的事情(比如使用自制图像加载器或其他东西),否则当没有任何引用它们时,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或类似的,那么通过它运行代码可能会给您一些提示。

如果从磁盘或嵌入到程序集中的资源加载图像,您还可以尝试查看它是否有任何区别。

如何不首先消耗所有内存?

注意:以下段落和代码是从这个答案中复制的。)

部分问题是它正在加载每个中的完整图像。 您必须使用IValueConverter通过在BitmapImage上设置DecodePixelWidthDecodePixelHeight属性来打开缩略图大小的每个图像。 这是我在我的一个项目中使用的一个例子……

 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(); } } 

您可能还想在Binding考虑IsAsync=True ,以便在后台线程上调用转换器。