如何在WP7中实时监控内存使用量


在windows phone 7 里开发的程序在运行过程中如果内存使用超过90M程序就会自动退出,但是在模拟器上没有这个限制,因此必须有方法帮助你在调试程序的时候时刻监控内存占用,否则即使在模拟器上没问题,一旦到了真机上就可能会出问题,最近在开发中我就遇到了这个问题,经过摸索,发现phone7提供了DeviceExtendedProperties可用于取得内存使用情况。

办法一:在app.xaml.cs里加入一个timer, 设置每间隔一段时间输出内存占用值到控制台:

1.在app.xaml.cs里添加下列函数:

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 : " + deviceTotalMemory.ToString());
System.Diagnostics.Debug.WriteLine("App Current : " + applicationCurrentMemoryUsage.ToString());
System.Diagnostics.Debug.WriteLine("App Peak : " + applicationPeakMemoryUsage.ToString());
}

2。在构造函数public App{}里添加 :

System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(1000d);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();

办法二:

使用MemoryDiagnosticsHelper.cs类,下面是源代码,将此文件添加到工程中。

然后将MemoryDiagnosticsHelper.Start(TimeSpan.FromMilliseconds(500), true); 这一句添加到构造函数public App{}里

if (System.Diagnostics.Debugger.IsAttached)

{

...
MemoryDiagnosticsHelper.Start(TimeSpan.FromMilliseconds(500), true);

...

}

用模拟器debug你的程序,手机界面右侧边会多出一条显示实时内存状态的信息。

代码
usingSystem;
usingSystem.Net;
usingSystem.Windows;
usingSystem.Windows.Controls;
usingSystem.Windows.Documents;
usingSystem.Windows.Ink;
usingSystem.Windows.Input;
usingSystem.Windows.Media;
usingSystem.Windows.Media.Animation;
usingSystem.Windows.Shapes;
usingSystem.Windows.Controls.Primitives;
usingSystem.Windows.Threading;
usingMicrosoft.Phone.Info;
usingSystem.Diagnostics;
usingSystem.Collections.Generic;

namespaceMemoryDiagnostics
{
///<summary>
///Helperclassforshowingcurrentmemoryusage
///</summary>
publicstaticclassMemoryDiagnosticsHelper
{
staticPopuppopup;
staticTextBlockcurrentMemoryBlock;
staticTextBlockpeakMemoryBlock;
staticDispatcherTimertimer;
staticboolforceGc;
constlongMAX_MEMORY=90*1024*1024;//90MB,permarketplace
staticintlastSafetyBand=-1;//toavoidneedlesschangesofcolour

constlongMAX_CHECKPOINTS=10;//adjustasneeded
staticQueue<MemoryCheckpoint>recentCheckpoints;

staticboolalreadyFailedPeak=false;//toavoidendlessAsserts

///<summary>
///Startsthememorydiagnostictimerandshowsthecounter
///</summary>
///<paramname="timespan">Thetimespanbetweencounterupdates</param>
///<paramname="forceGc">WhetherornottoforceaGCbeforecollectingmemorystats</param>
[Conditional("DEBUG")]
publicstaticvoidStart(TimeSpantimespan,boolforceGc)
{
if(timer!=null)
thrownewInvalidOperationException("Diagnosticsalreadyrunning");

MemoryDiagnosticsHelper.forceGc
=forceGc;
recentCheckpoints
=newQueue<MemoryCheckpoint>();

StartTimer(timespan);
ShowPopup();
}

///<summary>
///Stopsthetimerandhidesthecounter
///</summary>
[Conditional("DEBUG")]
publicstaticvoidStop()
{
HidePopup();
StopTimer();
recentCheckpoints
=null;
}

///<summary>
///Addacheckpointtothesystemtohelpdiagnosefailures.Ignoredinretailmode
///</summary>
///<paramname="text">Texttodescribethemostrecentthingthathappened</param>
[Conditional("DEBUG")]
publicstaticvoidCheckpoint(stringtext)
{
if(recentCheckpoints==null)
return;

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

recentCheckpoints.Enqueue(
newMemoryCheckpoint(text,GetCurrentMemoryUsage()));
}

///<summary>
///Recentcheckpointsstoredbytheapp;willalwaysbeemptyinretailmode
///</summary>
publicstaticIEnumerable<MemoryCheckpoint>RecentCheckpoints
{
get
{
if(recentCheckpoints==null)
yieldbreak;

foreach(MemoryCheckpointcheckpointinrecentCheckpoints)
yieldreturncheckpoint;
}
}

///<summary>
///Getsthecurrentmemoryusage,inbytes.Returnszeroinnon-debugmode
///</summary>
///<returns>Currentusage</returns>
publicstaticlongGetCurrentMemoryUsage()
{
#ifDEBUG
//don'tuseDeviceExtendedPropertiesforreleasebuilds(requiresacapability)
return(long)DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage");
#else
return0;
#endif
}

///<summary>
///Getsthepeakmemoryusage,inbytes.Returnszeroinnon-debugmode
///</summary>
///<returns>Peakmemoryusage</returns>
publicstaticlongGetPeakMemoryUsage()
{
#ifDEBUG
//don'tuseDeviceExtendedPropertiesforreleasebuilds(requiresacapability)
return(long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage");
#else
return0;
#endif
}

privatestaticvoidShowPopup()
{
popup
=newPopup();
doublefontSize=(double)Application.Current.Resources["PhoneFontSizeSmall"]-2;
Brushforeground
=(Brush)Application.Current.Resources["PhoneForegroundBrush"];
StackPanelsp
=newStackPanel{Orientation=Orientation.Horizontal,Background=(Brush)Application.Current.Resources["PhoneSemitransparentBrush"]};
currentMemoryBlock
=newTextBlock{Text="---",FontSize=fontSize,Foreground=foreground};
peakMemoryBlock
=newTextBlock{Text="",FontSize=fontSize,Foreground=foreground,Margin=newThickness(5,0,0,0)};
sp.Children.Add(currentMemoryBlock);
sp.Children.Add(
newTextBlock{Text="kb",FontSize=fontSize,Foreground=foreground});
sp.Children.Add(peakMemoryBlock);
sp.RenderTransform
=newCompositeTransform{Rotation=90,TranslateX=480,TranslateY=425,CenterX=0,CenterY=0};
popup.Child
=sp;
popup.IsOpen
=true;
}

privatestaticvoidStartTimer(TimeSpantimespan)
{
timer
=newDispatcherTimer();
timer.Interval
=timespan;
timer.Tick
+=newEventHandler(timer_Tick);
timer.Start();
}

staticvoidtimer_Tick(objectsender,EventArgse)
{
if(forceGc)
GC.Collect();

UpdateCurrentMemoryUsage();
UpdatePeakMemoryUsage();
}

privatestaticvoidUpdatePeakMemoryUsage()
{
if(alreadyFailedPeak)
return;

longpeak=GetPeakMemoryUsage();
if(peak>=MAX_MEMORY)
{
alreadyFailedPeak
=true;
Checkpoint(
"*MEMORYUSAGEFAIL*");
peakMemoryBlock.Text
="FAIL!";
peakMemoryBlock.Foreground
=newSolidColorBrush(Colors.Red);
if(Debugger.IsAttached)
Debug.Assert(
false,"Peakmemoryconditionviolated");
}
}

privatestaticvoidUpdateCurrentMemoryUsage()
{
longmem=GetCurrentMemoryUsage();
currentMemoryBlock.Text
=string.Format("{0:N}",mem/1024);
intsafetyBand=GetSafetyBand(mem);
if(safetyBand!=lastSafetyBand)
{
currentMemoryBlock.Foreground
=GetBrushForSafetyBand(safetyBand);
lastSafetyBand
=safetyBand;
}
}

privatestaticBrushGetBrushForSafetyBand(intsafetyBand)
{
switch(safetyBand)
{
case0:
returnnewSolidColorBrush(Colors.Green);

case1:
returnnewSolidColorBrush(Colors.Orange);

default:
returnnewSolidColorBrush(Colors.Red);
}
}

privatestaticintGetSafetyBand(longmem)
{
doublepercent=(double)mem/(double)MAX_MEMORY;
if(percent<=0.75)
return0;

if(percent<=0.90)
return1;

return2;
}

privatestaticvoidStopTimer()
{
timer.Stop();
timer
=null;
}

privatestaticvoidHidePopup()
{
popup.IsOpen
=false;
popup
=null;
}
}

///<summary>
///Holdscheckpointinformationfordiagnosingmemoryusage
///</summary>
publicclassMemoryCheckpoint
{
///<summary>
///Createsanewinstance
///</summary>
///<paramname="text">Textforthecheckpoint</param>
///<paramname="memoryUsage">Memoryusageatthetimeofthecheckpoint</param>
internalMemoryCheckpoint(stringtext,longmemoryUsage)
{
Text
=text;
MemoryUsage
=memoryUsage;
}

///<summary>
///Thetextassociatedwiththischeckpoint
///</summary>
publicstringText{get;privateset;}

///<summary>
///Thememoryusageatthetimeofthecheckpoint
///</summary>
publiclongMemoryUsage{get;privateset;}
}
}

优质内容筛选与推荐>>
1、python 4
2、ACS被集成到了Windows Azure Management Portal中
3、Java多线程系列 基础篇09 Object.wait/notifyJVM源码实现
4、分享知识-快乐自己:SpringMvc中的单多文件上传及文件下载
5、shell进程中的特殊状态变量


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn