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

时间:2008-10-09 01:55:02

标签: c# wpf memory-management

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

<Image x:Name="ItemImage" Source="{Binding ImageUrl}"/> 

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

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

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

2 个答案:

答案 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上的DecodePixelHeightBitmapImage属性,以缩略图大小打开每个图片。这是我在我的一个项目中使用的一个例子......

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,以便在后台线程中调用转换器。