在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 42、ACS被集成到了Windows Azure Management Portal中3、Java多线程系列 基础篇09 Object.wait/notifyJVM源码实现4、分享知识-快乐自己:SpringMvc中的单多文件上传及文件下载5、shell进程中的特殊状态变量
长按二维码向我转账
受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。
阅读
好看
已推荐到看一看
你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
取消
分享想法到看一看
确定
最多200字,当前共字