UWP开发入门(十六)——常见的内存泄漏的原因
本篇借鉴了同事翔哥的劳动成果,在巨人的肩膀上把稿子又念了一遍。
内存泄漏的概念我这里就不说了,之前《UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏》中提到过,即使有垃圾回收机制,写C#还是有可能发生内存泄漏。
一般来说,以下两种情况会导致内存泄漏:
- 对象用完了但是没有释放资源
 
- 对象本身是做了清理内存的操作,但是对象内部的子对象没有成功释放资源
 
下面就UWP开发中具体的实例来说明需要避免的写法
- 从static/global的对象上注册了事件
 
FakeService.Instance.ShowMeTheMoneyEvent += Instance_ShowMeTheMoneyEvent;
比如我们有一个底层的FakeService,提供整个APP生命周期的数据和网络的访问。假设某个页面+=了这个FackService的Event,在离开页面时没有-=掉。那么该页面就无法被垃圾回收。
合理的做法是在OnNavigatedFrom方法里,把事件反注册掉。
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
FakeService.Instance.ShowMeTheMoneyEvent -= Instance_ShowMeTheMoneyEvent;
}
- DispatcherTimer事件未关闭
 
这种情况就属于对象内部的属性未能被释放,假设页面内部存在Timer对象:
public sealed partial class TimerPage : Page
{
private DispatcherTimer Timer { get; set; } = new DispatcherTimer(); public ArrayList arrayList { get; set; } public TimerPage()
{
this.InitializeComponent();
arrayList = new ArrayList();
Timer.Tick += Timer_Tick;
Timer.Interval = TimeSpan.FromSeconds();
Timer.Start();
} private void Timer_Tick(object sender, object e)
{
int count = ;
int.TryParse(TextBoxTimer.Text, out count);
count += ;
TextBoxTimer.Text = count.ToString();
} private void Button_Click(object sender, RoutedEventArgs e)
{
this.Frame.GoBack();
} protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
Timer.Stop();
}
}
如果在离开页面之前,未调用Timer对象的Stop方法,也未-=Tick事件(这里Stop方法会自动-=Tick事件)。该页面就不能正常的回收。
这里并不是说所有的Event都需要在OnNavigatedFrom方法中-=,例如Control本身的Loaded、IsEnabledChanged等事件等并不会造成内存泄漏,反注册这些事件是为了避免事件的重复触发。而DispatcherTimer比较特殊,我理解它会把自己加到一个专门维护计时器的队列中,然后不停的触发Tick事件,如果没有Stop或-=,就等于Timer一直引用了外部的对象,从而导致页面本身也无法回收。
- Data Binding Memory Leak
 
这一条在很多的文档上有所提及,很遗憾我没法通过Diagnostic Tools监测出来具体的泄漏,我猜测可能是很小规模的内存泄漏。但是避免的方式非常容易,只要平时写XAML注意一下就可以了。
会出现问题的写法是以下两种:
- 未实现INotifyPropertyChanged的对象,而你又想监测Property变化
 - 未实现INotifyCollectionChanged 接口的集合,而你又想监测Collection变化
 
其实很好处理。如果想监测变化,就老老实实继承对应的接口。如果使用了普通的Property和集合,并且不想监测变化,一定记得Mode = OneTime。
当然如果属性本身是dependency property,就不存在内存泄漏的情况了。
<!--内存泄漏,因为Children集合没有实现INotifyPropertyChanged来通知Count属性变化-->
<TextBlock Text="{Binding ElementName=layoutRoot, Path=Children.Count}" />
<!--不会内存泄漏,因为ActualWidth是依赖属性-->
<TextBlock Text="{Binding ElementName=layoutRoot, Path=ActualWidth}" />
<!--不会内存泄漏,因为Mode = OneTime-->
<TextBlock Text="{Binding ElementName=layoutRoot, Path=Children.Count, Mode = OneTime}" />
- 非托管资源的释放
 
这个都非常熟悉,不多说了。主要是通过using语句,或者在try { … } finally { … }中调用Dispose或者Close方法来释放非托管资源。
UWP开发入门(十六)——常见的内存泄漏的原因的更多相关文章
- Android内存管理(13)常见产生内存泄漏的原因
		
1.集合类泄漏 集合类如果仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用.如果这个集合类是全局性的变量 (比如类中的静态属性,全局性的 map 等即有静态引用或 final 一直指向它), ...
 - UWP开发入门(六)——对多设备不同分辨率显示效果的讨论
		
本篇不涉及具体代码,而是把实际开发UWP APP的过程中,遇到的不同设备,不同分辨率显示效果差异的问题进行讨论.希望能够抛砖引玉,和各位擦出一些火花. 蜀黍我目前是在做一套牛逼的UWP APP啦,目标 ...
 - UWP开发入门(十)——通过继承来扩展ListView
		
本篇之所以起这样一个名字,是因为重点并非如何自定义控件,不涉及创建CustomControl和UserControl使用的Template和XAML概念.而是通过继承的方法来扩展一个现有的类,在继承的 ...
 - UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏
		
因为.NET的垃圾回收机制相当完善,通常情况下我们是不需要关心内存泄漏的.问题人一但傻起来,连自己都会害怕,几个页面跳啊跳的,内存蹭蹭的往上涨,拉都拉不住.这种时候我们就需要冷静下来,泡一杯热巧克力. ...
 - S3C2416裸机开发系列十六_sd卡驱动实现
		
S3C2416裸机开发系列十六 sd卡驱动实现 象棋小子 1048272975 SD卡(Secure Digital Memory Card)具有体积小.容量大.传输数据快.可插拔.安全性好等长 ...
 - UWP开发入门系列笔记之(一):UWP初览
		
标签: 随着微软Build2015带来的好消息,Win10正式版发布的日子已经离我们越来越近了,我们也终于欣喜地看到:一个统一的Windows平台对于开发人员来说充满了吸引力,这局棋下的好大的说--于 ...
 - Android开发 |常见的内存泄漏问题及解决办法
		
在Android开发中,内存泄漏是比较常见的问题,有过一些Android编程经历的童鞋应该都遇到过,但为什么会出现内存泄漏呢?内存泄漏又有什么影响呢? 在Android程序开发中,当一个对象已经不需要 ...
 - 5个Android开发中比较常见的内存泄漏问题及解决办法
		
android中一个对象已经不需要了,但是其他对象还持有他的引用,导致他不能回收,导致这个对象暂存在内存中,这样内存泄漏就出现了. 内存泄漏出现多了,会是应用占用过多的没存,当占用的内存超过了系统 ...
 - UWP开发入门(四)——自定义CommandBar
		
各位好,再次回到UWP开发入门系列,刚回归可能有些不适应,所以今天我们讲个简单的,自定义CommandBar,说通俗点就是自定义类似AppBarButton的东西,然后扔到CommandBar中使用. ...
 
随机推荐
- Revit如何修改云线批注外观
			
Revit云线批注属于注释族类别,有两种方式可以修改云线批注的外观,有两处设置可以修改云线批注的颜色线宽等外观,一个是视图属性"可见性/图形替换"对话框,另一个是菜单"管 ...
 - 混合使用Jquery Deferred和Angularjs的$timeout(转)
			
原文链接:http://my.oschina.net/gejiawen0913/blog/174826 <!DOCTYPE html> <html ng-app="Demo ...
 - java中获取比毫秒更为精确的时间
			
所以这里提醒做非常精确的时间统计的朋友,谨慎使用System.currentTimeMillis() . 在Java中可以通过System.currentTimeMillis()或者System.na ...
 - 【linux】文件隐藏属性
			
这些隐藏的属性确实对于系统有很大的帮助的- 尤其是在系统安全 (Security) 上面,重要的紧呢!不过要先强调的是,底下的chattr指令只能在Ext2/Ext3的文件系统上面生效, 其他 ...
 - wdlinux  一键安装
			
Linux系统(支持CentOS 6.X/7.X.RedHat 6.X.Ubuntu 12.04): ssh登录服务器,执行如下操作即可,需root用户身份安装 wget http://dl.wdli ...
 - TargetProcess公司敏捷开发历程-开发实践篇
 - 深入剖析 redis 事件驱动
			
概述 redis 内部有一个小型的事件驱动,它和 libevent 网络库的事件驱动一样,都是依托 I/O 多路复用技术支撑起来的. 利用 I/O 多路复用技术,监听感兴趣的文件 I/O 事件,例如读 ...
 - Myeclipse设置JAVA选中高亮显示
			
1.打开显示功能 选择Windows->Preferences->Java-> Editor-> Mark Occurrences ,勾选选项.这时,当你单击一个元素的时候,代 ...
 - 【cocos2d-x 手游研发----目录】
			
感谢大家一直支持我写这样一系列的博客,从中我自己也获益良多,cocos2d-x这样一款非常棒的引擎,是值得我们去学习和分享的,谈到分享,那我就把这套写了差不多一两个月的框架给大家开源下载,写的很一般, ...
 - UIRefreshControl的使用
			
注意: 1.需要在ios6.0之后的版本中使用 2.UIRefreshControl目前只能用于UITableViewController,如果用在其他ViewController中,运行时会错误(即 ...