• Silverlight内存问题总结(四)—用Listbox 来模拟实现轻量级的TreeView控件,解决内存暴涨上百M的问题


    When using a child window control, memory used by the control does not get released or freed when the control closes. Here are the steps to reproduce the issue.

    1. 1.       Create a new Silverlight project.
    2. 2.       Add Child Window Control.
    3. 3.       Add any large png file. It helps with memory tracking later on.
    4. 4.       In MainPage.xaml:

          a.       Add a button:  

           <Button Content="Click" Click="Button_Click" Width="100" Height="50"></Button>

    1. 5.       In MainPage.xaml.cs:

                 a.      //  The Child Window  

            ChildWindow1 mywin;  

            void Button_Click(object sender, RoutedEventArgse) 

            { 

              mywin = new ChildWindow1();// hook closed event the release mywin object            、

              mywin.Closed += new EventHandler(win_Closed);            

              mywin.Show();        

            }        

            void win_Closed(object sender, EventArgs e)

            {// unhook event and release mywin object           

               mywin.Closed -= win_Closed;           

               mywin = null;

      }

    1. 6.       In ChildWindow1.xaml

          a.       Add Image to help track memory usage

             <Grid.Background>           

                 <ImageBrush ImageSource="Images/background1.png" Stretch="UniformToFill"   />

       </Grid.Background>

    1. 7.       Run the application.
    2. 8.       Open Task Manager and locate the process that is hosting the application:  iexplorer.exe. Make a note of the current memory usage, ie 25876k
    3. 9.       Click the button in the app to open the child window. Again note the memory usage, ie. 33400k
    4. 10.   Close the child window. The memory usage never goes back to the initial 25876k

    This is quite a big issue for us, since we have create  an application that uses numerous child windows. After 4 hours of usage iexplorer.exe uses over 1.5 GB memory.

    Can this be resolved or is there any work around.

         上面的一段话是我在国外论坛上看到的一个帖子,非常的典型,Silverlight有很多类似的问题的,UI对象创建后,用完了,销毁掉,内存就是没办法释放掉,微软好像也无能为力的样子。其实这些问题都有一个共同特点:对象的引用明明销毁掉,但是内存就是回收不了,其实这个时候往往有一个你看不见也想不到指针或者事件指向它,这个指针往往在控件的使用上是必须的。基于以上的一个共同特点,高手都推荐用 ”弱引用” 来解决此类问题。”弱引用“ 是对象介于 可回收状态和强引用状态之间的一个状态,有兴趣的人可以去看Jeffrey Richer写的一本叫《.net 框架程序设计》,里面对垃圾回收器的回收算法,代龄,强引用,弱引用,对象池,以及非托管资源的释放,都有很详细的描述。“弱引用”方法原理很简单,重写微软的控件,把那个看不见,想不到的强引用指针改弱引用,这样时间久了,垃圾回收器会去回收对象的资源,简单地讲,"弱引用"是一种可以回收的,可以不回收的状态。原理很简单,但是做起来确很复杂,很多时候都不知道从那里开始,我中间尝试过几次都没有成功,看到这里请记下来一个很重要的专业名词“弱引用”。

        上面是讲一些原理东西,下面讲一下实际项目的应用

       项目中用到一个Silverlight 的 TreeView控件,对于小数据量的东西,Silverlight 的TreeView控件做得还是很不错的,该有的功能都有,简单好用,功能强大。但是对大数据量东西,就会出现瓶颈。我实际项目中有1万多辆车加上一些区域,每个区域,每个车辆都是树形目录上的一个节点,也就是我将近有2万个节点,这两万个结点数据绑上去还不错,可是一张开子节点,并且子节点稍微多一点,这个时候内存会涨上百M。后面我想了想用异步的方式加载,收缩的时候就把节点从界面上清除掉,这样可以减少内存,等异步的方式出来后我发现内存回收不干净,总有一些残余,而且量还是比较大的,即使我疯狂地使用 Jeffrey Richer  推荐的强制回收的方法:

     GC.Collect();

     GC.WaitForPending();

     GC.Collect();

    我点了N次,这三行代码执行了N次,鼠标都快被我点坏了,还是回收的不干净,干!于是乎我绝望,我再一次想到了”弱引用“,很遗憾”弱引用“比较难实现,而且效果不一定行,因为可能有多个指针指到这个内存块,那些指针都不知道,弱引用是没办法用的。

       想到用Listbox来模拟实现TreeView ,应该来说是非常偶然的。一次非常偶然的机会,我使用silverlight 的Listbox,我给Listbox增加5000个节点我发现内存没怎么涨,就涨了不到10M,我在增加1万个节点,发现内存居然不涨,于是乎我就很自然的想到用Listbox模拟TreeView,而且内存就是涨了10M,能不能回收根本就无所谓 。至于怎么模拟,那是很简单的事情,纯粹就是体力活,有空把代码贴出来。

  • 相关阅读:
    MySQL--单表查询
    python库--pandas--Series.str--字符串处理
    如何 grep tab & 如何grep 减号(dash)
    png压缩
    如何无密码登陆远程机器?
    ssh中运行awk
    PHP 时区
    sublime使用
    nginx 50x故障分析
    nginx反向代理异常
  • 原文地址:https://www.cnblogs.com/zhengjianfeng/p/1863470.html
Copyright © 2020-2023  润新知