none
ListView启动虚拟化加载缩略图,实现了滚动条当前所在加载的图片的缩略图,非滚动条当前所在区域销毁以前加载图片的缩略图,但是还是有内存只增不减的情况,要怎么解决? RRS feed

  • 常规讨论

  • Listview使用虚拟化容器加载大量的缩略图,使用了两个第三方控件,开源的虚拟化容器VirtualizingTilePanel和继承于Image控件的ThrumbImage控件,第三方控件ThrumbImage是在CSDN下载频道上从他人项目中抠出来的,简介中说可以降低内存,异步加载图片,与图片资源隔离,加载完毕之后不会再试用图片资源。

    我把这两个控件应用到我的项目的Listview控件中,VirtualizingTilePanel虚拟化容器配合ThrumbImage控件,实现滚动条的当前所在区域加载缩略图,非滚动条所在区域销毁缩略图(滚动条不在的区域,以前加载的缩略图会消失)。但是还有我最烦的内存只增不减的问题。每次加载新图片的缩略图时,以前加载的图片缩略图的内存还是不释放,只增不减,不知道怎么解决。由于使用的是两个第三方控件,我不好发代码,我还是直接发项目下载地址吧,项目不大。请求大神帮我解决一下内存只增不减的问题。

    项目下载地址:http://pan.baidu.com/s/1jIjWvfo

    如何在滚动条停止移动后先释放以前加载的图片的缩略图的内存,在去加载新图片的缩略图呢?或者还有其他办法?请求大神帮我解决一下内存只增不减的问题。或者有没有更好第三方控件?







    2016年11月13日 8:51

全部回复

  • 您好 轮回的齿轮,

    您的代码的问题主要体现在两方面。

    1.  托管内存没有及时释放。需要在VirtualizingTilePanel的CleanUpItems方法最后加上 GC.Collect()。

    private void CleanUpItems(int minDesiredGenerated, int maxDesiredGenerated)
    {
        UIElementCollection children = this.InternalChildren;
        IItemContainerGenerator generator = this.ItemContainerGenerator;
    
        for (int i = children.Count - 1; i >= 0; i--)
        {
            GeneratorPosition childGeneratorPos = new GeneratorPosition(i, 0);
            int itemIndex = generator.IndexFromGeneratorPosition(childGeneratorPos);
            if (itemIndex < minDesiredGenerated || itemIndex > maxDesiredGenerated)
            {
                generator.Remove(childGeneratorPos, 1);
                RemoveInternalChildRange(i, 1);
            }
        }
    
        GC.Collect();
    }

    2. 如何正确的Load图片到图片控件中,保证图片会被及时释放。我修改了你ThrumbImage类中SetImageSource方法的代码。

    private static void SetImageSource(System.Windows.Controls.Image image, string fileName)
    {
        if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName))
        {
            BitmapImage img = new BitmapImage();
            img.BeginInit();
            img.CacheOption = BitmapCacheOption.OnLoad;
            img.UriSource = new Uri(fileName);
            img.EndInit();
            image.Source = img;
        }
    }

    通过以上修改之后,我这面测试代码的结果是,内部会在拖动滚动条的时候跳动,但是不会只升不降。

    Best Regards,
    Li Wang


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2016年11月15日 6:45
  • 您好 轮回的齿轮,

    您的代码的问题主要体现在两方面。

    1.  托管内存没有及时释放。需要在VirtualizingTilePanel的CleanUpItems方法最后加上 GC.Collect()。

    private void CleanUpItems(int minDesiredGenerated, int maxDesiredGenerated)
    {
        UIElementCollection children = this.InternalChildren;
        IItemContainerGenerator generator = this.ItemContainerGenerator;
    
        for (int i = children.Count - 1; i >= 0; i--)
        {
            GeneratorPosition childGeneratorPos = new GeneratorPosition(i, 0);
            int itemIndex = generator.IndexFromGeneratorPosition(childGeneratorPos);
            if (itemIndex < minDesiredGenerated || itemIndex > maxDesiredGenerated)
            {
                generator.Remove(childGeneratorPos, 1);
                RemoveInternalChildRange(i, 1);
            }
        }
    
        GC.Collect();
    }

    2. 如何正确的Load图片到图片控件中,保证图片会被及时释放。我修改了你ThrumbImage类中SetImageSource方法的代码。

    private static void SetImageSource(System.Windows.Controls.Image image, string fileName)
    {
        if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName))
        {
            BitmapImage img = new BitmapImage();
            img.BeginInit();
            img.CacheOption = BitmapCacheOption.OnLoad;
            img.UriSource = new Uri(fileName);
            img.EndInit();
            image.Source = img;
        }
    }

    通过以上修改之后,我这面测试代码的结果是,内部会在拖动滚动条的时候跳动,但是不会只升不降。

    Best Regards,
    Li Wang


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    在CleanUpItems方法的最后步骤加上一个cg方法释放托管内存。

    运行测试:

    1.用鼠标缓慢的移动滚动条时虽然还是时不时内存有增长不减的现象,但是比以前要好点。起码慢慢拖动滚动条增内只增不减的概率小了很多。

    2.尝试用鼠标快速拖动滚动条到我想浏览的区域,内存增长不减的现象还是有的。不过也比也以前稍微好一点。

    3.用鼠标修改程序窗口尺寸不断变大变小(另一个项目),内存增长不减的现象还是有的。不过也比也以前稍微好一点。当然最容易想到的解决办法是,程序窗口只能全屏浏览。

    4当我对绑定的数据集合调用clear()清除集合内容,然后在调用GC.Collect()。内存没有释放

    而修改SetImageSource方法我试过,拖动滚动条的时候内存增长过快,看起来似乎没有释放,不如原来SetImageSource方法。






    2016年11月16日 4:04
  • 您好 轮回的齿轮,

    >>"而修改SetImageSource方法我试过了,拖动滚动条的时候内存增长过快,看起来似乎没有释放,不如原来SetImageSource方法。"

    我这面测试的时候,使用修改后的SetImageSource方法,内存增长的速度快,但是释放的速度也比较快。我再仔细看下你使用的三方代码,发现问题了我会及时通知你。

    Best Regards,
    Li Wang


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2016年11月17日 10:07