WP7实时监控内存-转

一、第一种方法:

  Windows phone7提供的DeviceExtendedProperties可用于取得内存使用情况。app.xaml.cs:

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

    //设置每间隔一段时间输出内存占用值到控制台
        private void timer_Tick(object sender, EventArgs e)
        {
            //GC.GetTotalMemory(true);
            long deviceTotalMemory = (long)Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("DeviceTotalMemory");
            long applicationCurrentMemoryUsage = (long)Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage");
            long applicationPeakMemoryUsage = (long)Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage");
            System.Diagnostics.Debug.WriteLine(DateTime.Now.ToLongTimeString());
            System.Diagnostics.Debug.WriteLine("Device Total 设备使用的总内存              :\t" + deviceTotalMemory.ToString());
            System.Diagnostics.Debug.WriteLine("App Peak 当前应用程序可用的最大内存    :\t" + applicationPeakMemoryUsage.ToString());
            System.Diagnostics.Debug.WriteLine("App Current 当前应用程序已用的内存     :\t" + applicationCurrentMemoryUsage.ToString());
        }

        public App()

        {
            timer.Interval = TimeSpan.FromMilliseconds(1000d);
            timer.Tick += new EventHandler(timer_Tick);
            timer.Start();
        }

二、第二种方法

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using System.Windows.Threading;
using Microsoft.Phone.Info;
using System.Diagnostics;
using System.Collections.Generic;

namespace WindowsPhone7
{
    /// <summary>
    /// 内存监控类:
    /// App.xaml.cs的析构函数里调用:MemoryDiagnosticsHelper.Start(TimeSpan.FromMilliseconds(500), true);
    /// Debug模式下,模拟器或设备中运行,手机右侧实时显示内存状态
    /// </summary>
    public static class MemoryDiagnosticsHelper
    {
        static Popup popup;
        static TextBlock currentMemoryBlock;
        static TextBlock peakMemoryBlock;
        static DispatcherTimer timer;
        static bool forceGc;
        const long MAX_MEMORY = 90 * 1024 * 1024; // 90MB, per marketplace
        static int lastSafetyBand = -1; // to avoid needless changes of colour

        const long MAX_CHECKPOINTS = 10; // adjust as needed
        static Queue<MemoryCheckpoint> recentCheckpoints;

        static bool alreadyFailedPeak = false; // to avoid endless Asserts

        /// <summary>
        /// Starts the memory diagnostic timer and shows the counter
        /// </summary>
        /// <param name="timespan">The timespan between counter updates</param>
        /// <param name="forceGc">Whether or not to force a GC before collecting memory stats</param>
        [Conditional("DEBUG")]
        public static void Start(TimeSpan timespan, bool forceGc)
        {
            if (timer != null)
                throw new InvalidOperationException("Diagnostics already running");

            MemoryDiagnosticsHelper.forceGc = forceGc;
            recentCheckpoints = new Queue<MemoryCheckpoint>();

            StartTimer(timespan);
            ShowPopup();
        }

        /// <summary>
        /// Stops the timer and hides the counter
        /// </summary>
        [Conditional("DEBUG")]
        public static void Stop()
        {
            HidePopup();
            StopTimer();
            recentCheckpoints = null;
        }

        /// <summary>
        /// Add a checkpoint to the system to help diagnose failures. Ignored in retail mode
        /// </summary>
        /// <param name="text">Text to describe the most recent thing that happened</param>
        [Conditional("DEBUG")]
        public static void Checkpoint(string text)
        {
            if (recentCheckpoints == null)
                return;

            if (recentCheckpoints.Count >= MAX_CHECKPOINTS - 1)
                recentCheckpoints.Dequeue();

            recentCheckpoints.Enqueue(new MemoryCheckpoint(text, GetCurrentMemoryUsage()));
        }

        /// <summary>
        /// Recent checkpoints stored by the app; will always be empty in retail mode
        /// </summary>
        public static IEnumerable<MemoryCheckpoint> RecentCheckpoints
        {
            get
            {
                if (recentCheckpoints == null)
                    yield break;

                foreach (MemoryCheckpoint checkpoint in recentCheckpoints)
                    yield return checkpoint;
            }
        }

        /// <summary>
        /// Gets the current memory usage, in bytes. Returns zero in non-debug mode
        /// </summary>
        /// <returns>Current usage</returns>
        public static long GetCurrentMemoryUsage()
        {
#if DEBUG
            // don't use DeviceExtendedProperties for release builds (requires a capability)
            return (long)DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage");
#else
      return 0;
#endif
        }

        /// <summary>
        /// Gets the peak memory usage, in bytes. Returns zero in non-debug mode
        /// </summary>
        /// <returns>Peak memory usage</returns>
        public static long GetPeakMemoryUsage()
        {
#if DEBUG
            // don't use DeviceExtendedProperties for release builds (requires a capability)
            return (long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage");
#else
      return 0;
#endif
        }

        private static void ShowPopup()
        {
            popup = new Popup();
            double fontSize = (double)Application.Current.Resources["PhoneFontSizeSmall"] - 2;
            Brush foreground = (Brush)Application.Current.Resources["PhoneForegroundBrush"];
            StackPanel sp = new StackPanel { Orientation = Orientation.Horizontal, Background = (Brush)Application.Current.Resources["PhoneSemitransparentBrush"] };
            currentMemoryBlock = new TextBlock { Text = "---", FontSize = fontSize, Foreground = foreground };
            peakMemoryBlock = new TextBlock { Text = "", FontSize = fontSize, Foreground = foreground, Margin = new Thickness(5, 0, 0, 0) };
            sp.Children.Add(currentMemoryBlock);
            sp.Children.Add(new TextBlock { Text = " kb", FontSize = fontSize, Foreground = foreground });
            sp.Children.Add(peakMemoryBlock);
            sp.RenderTransform = new CompositeTransform { Rotation = 90, TranslateX = 480, TranslateY = 425, CenterX = 0, CenterY = 0 };
            popup.Child = sp;
            popup.IsOpen = true;
        }

        private static void StartTimer(TimeSpan timespan)
        {
            timer = new DispatcherTimer();
            timer.Interval = timespan;
            timer.Tick += new EventHandler(timer_Tick);
            timer.Start();
        }

        static void timer_Tick(object sender, EventArgs e)
        {
            if (forceGc)
                GC.Collect();

            UpdateCurrentMemoryUsage();
            UpdatePeakMemoryUsage();
        }

        private static void UpdatePeakMemoryUsage()
        {
            if (alreadyFailedPeak)
                return;

            long peak = GetPeakMemoryUsage();
            if (peak >= MAX_MEMORY)
            {
                alreadyFailedPeak = true;
                Checkpoint("*MEMORY USAGE FAIL*");
                peakMemoryBlock.Text = "FAIL!";
                peakMemoryBlock.Foreground = new SolidColorBrush(Colors.Red);
                if (Debugger.IsAttached)
                    Debug.Assert(false, "Peak memory condition violated");
            }
        }

        private static void UpdateCurrentMemoryUsage()
        {
            long mem = GetCurrentMemoryUsage();
            currentMemoryBlock.Text = string.Format("{0:N}", mem / 1024);
            int safetyBand = GetSafetyBand(mem);
            if (safetyBand != lastSafetyBand)
            {
                currentMemoryBlock.Foreground = GetBrushForSafetyBand(safetyBand);
                lastSafetyBand = safetyBand;
            }
        }

        private static Brush GetBrushForSafetyBand(int safetyBand)
        {
            switch (safetyBand)
            {
                case 0:
                    return new SolidColorBrush(Colors.Green);

                case 1:
                    return new SolidColorBrush(Colors.Orange);

                default:
                    return new SolidColorBrush(Colors.Red);
            }
        }

        private static int GetSafetyBand(long mem)
        {
            double percent = (double)mem / (double)MAX_MEMORY;
            if (percent <= 0.75)
                return 0;

            if (percent <= 0.90)
                return 1;

            return 2;
        }

        private static void StopTimer()
        {
            timer.Stop();
            timer = null;
        }

        private static void HidePopup()
        {
            popup.IsOpen = false;
            popup = null;
        }
    }

    /// <summary>
    /// Holds checkpoint information for diagnosing memory usage
    /// </summary>
    public class MemoryCheckpoint
    {
        /// <summary>
        /// Creates a new instance
        /// </summary>
        /// <param name="text">Text for the checkpoint</param>
        /// <param name="memoryUsage">Memory usage at the time of the checkpoint</param>
        internal MemoryCheckpoint(string text, long memoryUsage)
        {
            Text = text;
            MemoryUsage = memoryUsage;
        }

        /// <summary>
        /// The text associated with this checkpoint
        /// </summary>
        public string Text { get; private set; }

        /// <summary>
        /// The memory usage at the time of the checkpoint
        /// </summary>
        public long MemoryUsage { get; private set; }
    }
}

 

三、每个Page何时被释放:

  #if(DEBUG)
  /// <summary>
  /// Add a finalizer to check for memory leaks
  /// </summary>
  ~YourPage()
  {
    System.Diagnostics.Debug.WriteLine("Finalizing " + this.GetType().FullName);
  }
  #endif

  将这段代码添加到你的每一个page中,记得修改这个析构函数的名称哦。 那么当这个page被析构的时候,就会在output控制台里看到。

posted on 2011-09-30 10:33  chuncn  阅读(958)  评论(0编辑  收藏  举报

导航