5

我有一个列表框,里面有一堆图像(通过数据模板完成)。图像是通过设置项目来源创建的:

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

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

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

编辑:我忘了提一件事,图像(每个大小约为 4-5k)正在通过网络加载。缓存是否对此负责?显示 12 张图像会占用大约 10 兆的内存,大约是 100 倍的文件大小。

4

2 回答 2

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 或类似的,那么通过它运行您的代码可能会给您一些提示。

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

于 2008-10-09T12:08:48.557 回答
4

一开始就不要用完所有内存怎么样?

注意:以下段落和代码转载自此答案。)

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

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=TrueBinding后台线程上调用转换器。

于 2008-10-09T16:19:07.427 回答