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中使用. ...
随机推荐
- 转载:Cellebrite发布新版手机取证软件,增强调查能力
2012-5-24 7:57:51 文章来源:文传商讯 作者:文传商讯 UFED 1.1.9.7版本为移动取证数据提取.编码和分析提供了先进的技术突破 新闻事实: Cellebrite发布其旗舰产 ...
- CSS计数器的趣味时光
CSS计数器是“啊太好了,竟不知道CSS可以做这啊”这类非常有趣的众多特性之一.简言之,用CSS使你持续某增加某个量,而无需JavaScript. 简单计数器 我们从这个简单的分页示例开始: 你见到的 ...
- zookeeper节点Watch机制实例展示
znode以某种方式发生变化时,“观察”(watch)机制可以让客户端得到通知.可以针对ZooKeeper服务的“操作”来设置观察,该服务的其他 操作可以触发观察. 实现Watcher,复写proce ...
- android:themes.xml
<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2006 The Andr ...
- Oracle中group by用法
Oracle中group by用法 在select 语句中可以使用group by 子句将行划分成较小的组,一旦使用分组后select操作的对象变为各个分组后的数据,使用聚组函数返回的是每一个组的汇总 ...
- 解决mint17-linux里chrome一搞就弹出“登陆密钥环”的框框
摘自:https://sites.google.com/site/easylinuxtipsproject/tips#TOC-Make-the-keyring-password-on-your-com ...
- 前端开发者进阶之函数反柯里化unCurrying
函数柯里化,是固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩小适用范围,创建一个针对性更强的函数. 那么反柯里化函数,从字面讲,意义和用法跟函数柯里化相比正好相反,扩大适用 ...
- Hadoop源代码中的build-main.xml
在Hadoop的每一个Project中,都有build-main.xml,如下图所示: 这个文件其实是通过maven-ant插件生成的,在hadoop的每一个Maven工程中,都有一个pom文件,在p ...
- 结合仓库设计MVC控制器
为了更高效的开发MVC项目,我们对控制器进行了在一次的封装,使得控制器能够获得很好的继承关系,并能以更少 的代码,实现Web项目的开发工作,整个控制器的设计思路如下所示. 从上图的设计里面 ...
- 【Cocos2d-Js基础教学(6)网络层(弱联网)的封装及使用】
谈到联网,在游戏中也是非常核心的模块,在官方Js-test中我们可以找到联网部分 的NetworkTest文件下有两个类 SocketIOTest.js(Socket 类) WebSocketTest ...