处理列表框中WPF中的映像(内存泄漏)

本文关键字:内存 泄漏 映像 列表 WPF 处理 | 更新日期: 2023-09-27 17:47:49

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

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

然后通过使用列表框的项目来清除它们。Clear()方法。使用项目添加新图像。添加列表框的方法。

然而,内存使用率只是开始不断上升。显示的是大约300张小图像,但内存似乎从未被释放。该应用程序开始使用大约40Meg,并迅速攀升至700Meg。如何释放所有这些图像正在使用的内存?

编辑:有一件事我忘了提,图像(每个大小约4-5k)正在通过网络加载。缓存在某种程度上对此负责吗?显示12个图像会消耗大约10兆的内存,大约是文件大小的100倍。

处理列表框中WPF中的映像(内存泄漏)

除非你在加载图像时做了任何异常的事情(比如使用自制的图像加载程序或其他什么),否则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或类似的探查器,那么通过它运行代码可能会给您一些提示。

您也可以试着看看如果从磁盘或嵌入程序集中的资源加载图像是否有什么不同。

首先不要用完所有内存怎么样?

注意:下面的段落和代码是根据这个答案复制的。)

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

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