Windows Phone 内存检测方法

 

      在 VS 的开发环境中,有内存性能分析的工具(VS 的菜单栏——> 调试——> 启动 Windows Phone性能分析)

可以分析应用的内存占用情况,但是通常只有在程序停止运行结束后,我们才能看到数据。但是有时候我们想在程序

运行过程中时事看到内存占用情况,比如在执行某个特定的方法后获取内存信息。这里我写了一个简单的方法,在程序

运行时,每隔四秒就把内存信息打印到屏幕上,为了在应用的所有页面都可以检查,我们使用之前写过的一个自定义 Toast

输出框(文章和代码工程)。

   

      首先在页面的构造函数中,初始化一个 计时器:

            // 初始化计时器,每隔四秒钟就打印当前应用所占内存、峰值、和设备总内存

            dispacherTimer = new System.Windows.Threading.DispatcherTimer();

            dispacherTimer.Interval = TimeSpan.FromSeconds(4);

            dispacherTimer.Tick += new EventHandler(dispacherTimer_Tick);

定义定时器调用的方法:

        #region 内存使用情况

        static string total = "DeviceTotalMemory";

        static string current = "ApplicationCurrentMemoryUsage";

        static string peak = "ApplicationPeakMemoryUsage";



        static long totlaBytes;

        static long currentBytes;

        static long peakBytes;



        static System.Windows.Threading.DispatcherTimer dispacherTimer;

       

        void dispacherTimer_Tick(object sender, EventArgs e)

        {

            // 获取设备的总内存

            totlaBytes = (long)Microsoft.Phone.Info.DeviceExtendedProperties.GetValue(total);



            // 获取应用当前占用内存

            currentBytes = (long)Microsoft.Phone.Info.DeviceExtendedProperties.GetValue(current);



            // 获取内存占用的峰值

            peakBytes = (long)Microsoft.Phone.Info.DeviceExtendedProperties.GetValue(peak);

            

            // 使用自定义的 MyDialog 控件打印出来

            MyDialog.ShowToastMessage(string.Format("当前:{0:F2}MB;  峰值:{1:F2}MB;  总:{2:F2}MB;", currentBytes / (1024 * 1024.0), peakBytes / (1024 * 1024.0), totlaBytes / (1024 * 1024.0)));

        }

        #endregion

 

在xaml 页面中添加两个按钮,分别用来启动和关闭内存信息检测,相应的 C# 函数:

        // 取消内存信息打印,释放资源

        private void btnStop_Click(object sender, RoutedEventArgs e)

        {

            dispacherTimer.Stop();

            dispacherTimer.Tick -= new EventHandler(dispacherTimer_Tick);

            dispacherTimer = null;

        }



        // 开始向屏幕输出内存情况

        private void btnStart_Click(object sender, RoutedEventArgs e)

        {

            if (dispacherTimer != null)

            {

                dispacherTimer.Start();

            }

        }

 

显示截图:

Windows Phone 内存检测方法

 

    内存占用的问题在 WP 的开发中是比较棘手的。因为市面上的 Lumia系列的手机,很多都是一体机,无论是

800 还是 920,它们在运行应用时,如果你的应用持续占用超过 120MB 的内存,那么它的发热情况是非常明显

的。而且导致发热的问题主要是内存的问题,并非 CPU 消耗的问题,而且在传统的 Silverlight 应用中,相对于

游戏应用,使用的数学运算等等消耗 CPU 的资源往往是微不足道的。

    我在开发过程中,总结了内存占用的一些情况,其中最主要的是在页面中绘制的元素太多,或者页面的显示尺寸太

大,比如在一个 ListBox 中显示新闻,屏幕的高度是 800px,每屏显示 4条新闻,如果当前 ListBox 中共有24 条新闻,

那么该 ListBox 就是 6 屏 X 800px = 4800 px  的高度 !!!如果这 24条全部显示在页面中,内存占用是 60MB,

但是用户看到的有效信息只是屏幕中显示的 4条。所以把 ListBox 换成 LongListSelector (支持虚拟化和内存复用)

是很有必要的。如果想继续使用 ListBox 可以写一个算法(曾经写过),就是ListBox 只显示当前四条的新闻,其它

20条的新闻可以把它们的 Visibility 设置为 System.Windows.Visibility.Collapsed,当用户的手指划到那条新闻时,

再把那条新闻的该属性设置为  System.Windows.Visibility.Visible, 这样如果全部显示 24条新闻占用 60MB,那么

通过这个算法,内存只需要 25MB 左右。

      通常导致内存增加,可能是程序中一些不再使用的对象得不到有效的释放,这些对象越来越多,从而导致内存泄露,

可能的原因:

1)静态对象的引用

2)事件没有与方法解除订阅

3)静态事件没有与方法解除订阅

4)非托管资源(实现了 IDispose 接口),没有调用 Dispose 方法

5)非托管资源的 Dispose 方法没有执行完成

      另一个问题是,有的开发者在开放 WP8 的过程中,担心使用 async 和 await 关键字过多,会不会导致系统频繁创建

额外的线程过多,结果消耗很多系统资源。其实并非如此,因为在 .net 4.5 中引入的 async 和 await 关键字只是简化了

.net 4.0 中 Task 的创建和维护,通过使用同步编程的方式实现了异步线程的调用,并且 Task 在异步调用时,底层并非

创建了新的线程,而是使用的线程池技术,达到线程复用的目的。所以在 WP8 的开发中,尽可能的使用 async 和 await

因为它们不会增加应用过多占用系统的资源。

      最后还有一点建议,就是在程序开发的时候,比如在应用中需要显示网页内容,一个选择是在应用中放一个 WebBrowser

控件,除非迫不得已,否则尽可能调用  Microsoft.Phone.Tasks.WebBrowserTask, 从而使用系统的 IE 浏览器打开网页内容

,因为 WebBrowser 控件显示网页内容时,所占用的内存也是相当大的,而且使用 IE 打开网页内容,不但系统会优化系统

资源,而且它所占用的内存并不会算入到应用占用的内存中去。

        同理,相对于调用摄像头的 API(高级捕获 PhotoCaptureDevice 和 PhotoCamera ),最好使用系统任务:

Microsoft.Phone.Tasks.CameraCaptureTask。

你可能感兴趣的:(windows phone)