WPF/Silverlight应用程序长时间运行后会产生非常多的内存垃圾(内存泄露例外),特别是在经常需要进行Remove操作的粒子、动画、游戏等方面的应用,国外高手们提出的方案我归纳了一下主要有: 1) UIElement控件实例= null 2) 定时调用GC.Collect() 3) 让控件继承,并实现相应逻辑 这三种方法都有一定的作用,但是实际使用中均往往难以达到预期效果。特别是在Silverlight应用中,目前的Flash/Flex制作的RPG网页游戏都有一个通病:内存不断增加导致运行二、三十分钟后浏览器即进入假死状态,Silverlight如果无法处理好内存的释放,命运或许终究一样。 那么我们是否还有其他更好的方法实现内存垃圾的释放?大家不妨做这么一个测试,以IE浏览器为例,当我们打开一个运行有Silverlight应用程序的页面后,记录下任务管理器中该IEXPLORE.EXE的内存使用量,然后运行一段时间,再记录此时的内存使用量,{zh1}将该页面最小化再还原回来,大家将看到该IEXPLORE.EXE的内存使用量已被xx的释放干净,如同新开的网页一般。这老掉牙的东西已算不上什么技巧,但是却给了我们一条内存彻底释放的思路:既然Silverlight应用程序是镶嵌在网页中的,我们能否通过该方法去释放内存呢?答案是肯定的。 以我的为例,刚加载完时内存使用约56M:
然后我刷了80个怪,并将它们全部消灭干净后内存使用量约为132M:
接着将此页面最小化再还原,内存瞬间释放到约20M:
并且在不刷出新怪的前提下,我环绕整个地图走完每个角落后,内存{zd0}时不超过 很多朋友或许要说了:这些都是废话嘛,连蚂蚁都知道。难不成我还要在Silverlight页面上放个注释:客户们注意啦~为了您和浏览器的健康,请定时最小化浏览器。 其实我想和大家说的,这仅仅是一条思路。大家不妨想想,其实我们是xx可以将这种方法无缝的嵌入到页面中去的。 在Winform/WPF中,实现该方法仅仅只需通过下面一段代码即可实现模拟释放内存(): [DllImport("kernel32.dll")] public static extern bool SetProcessWorkingSetSize(IntPtr proc, int min, int max); public void FlushMemory() { GC.Collect(); GC.WaitForPendingFinalizers(); if (Environment.OSVersion.Platform == PlatformID.Win32NT) { SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1); } } 但是Windows的API无法在Silverlight中使用,我们该怎么办呢? 再看下面这段代码: <script type="text/javascript"> function intervalFlushMemory() { setInterval(FlushMemory, 60000); } function FlushMemory() { min.Click(); window.focus(); } </script> <body onload="intervalFlushMemory();"> …… <object id="min" type="data:application/x-oleobject" classid="clsid:adb <param name="Command" value="Minimize" /> </object> <button onclick="FlushMemory();">释放内存</button> …… </body>
非常不幸的是,通过<object>实现内存释放的方法目前只能在IE中使用,而且由于诸多限制还无法很好的广泛使用,解决的最终方法目前我只想到两个: 1) 能否有相关的Silverlight的API直接实现类似功能,或者后台代码C#中去实现呢? 2) 通过将该<object>制作成控件并打包成cab,并加上数字签名,以ActiveX的形式让用户使用,实在是够麻烦的… 文章要结尾了,但是我无法兴奋起来,C++开发者的冷眼嘲笑让我始终有种沉痛的感觉:Silverlight的内存垃圾本是可以轻松释放的,为何MS就不能让我们畅快一点?托管是否能更绅士些? {zh1},我想告诉大家的是,本文的目的并没有真正达到,因为这所有的方法都不是xx的解决方案,作为一些思路,我希望大家能给予我更多的指点,欢迎大家留言参与Silverlight内存的相关讨论,因为我们的最终目的只有一个:誓将内存释放到底! Silverlight还是个孩子,它的路还有很长要走;但我一直坚信:明天会更好。 源貼來自: |