原文:UWP开发入门(十六)——常见的内存泄漏的原因

  本篇借鉴了同事翔哥的劳动成果,在巨人的肩膀上把稿子又念了一遍。

  内存泄漏的概念我这里就不说了,之前《UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏》中提到过,即使有垃圾回收机制,写C#还是有可能发生内存泄漏。

  一般来说,以下两种情况会导致内存泄漏:

  1. 对象用完了但是没有释放资源
  1. 对象本身是做了清理内存的操作,但是对象内部的子对象没有成功释放资源

  下面就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(10000000);Timer.Tick += Timer_Tick;Timer.Interval = TimeSpan.FromSeconds(1);Timer.Start();}private void Timer_Tick(object sender, object e){int count = 0;int.TryParse(TextBoxTimer.Text, out count);count += 1;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注意一下就可以了。

  会出现问题的写法是以下两种:

  1. 未实现INotifyPropertyChanged的对象,而你又想监测Property变化
  2. 未实现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开发入门(十六)——常见的内存泄漏的原因相关推荐

  1. UWP开发入门(十九)——10分钟学会在VS2015中使用Git

    原文:UWP开发入门(十九)--10分钟学会在VS2015中使用Git 写程序必然需要版本控制,哪怕是个人项目也是必须的.我们在开发UWP APP的时候,VS2015默认提供了对微软TFS和Git的支 ...

  2. UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏

    因为.NET的垃圾回收机制相当完善,通常情况下我们是不需要关心内存泄漏的.问题人一但傻起来,连自己都会害怕,几个页面跳啊跳的,内存蹭蹭的往上涨,拉都拉不住.这种时候我们就需要冷静下来,泡一杯热巧克力. ...

  3. 【课程设计】UWP 开发入门小笔记(1)

    UWP 开发入门小笔记(1) 零.介绍 一.系列介绍[p1] 二.创建第一个属于自己的UWP应用[p2] (一)一个button的属性: (二)修改属性的三种方法 (三)字号(以后会细讲) 三.UWP ...

  4. S3C2416裸机开发系列十六_sd卡驱动实现

    S3C2416裸机开发系列十六 sd卡驱动实现 象棋小子    1048272975 SD卡(Secure Digital Memory Card)具有体积小.容量大.数据传输快.可插拔.安全性好等优 ...

  5. 5 个 Android 开发中比较常见的内存泄漏问题及解决办法

    Android开发中,内存泄漏是比较常见的问题,有过一些Android编程经历的童鞋应该都遇到过,但为什么会出现内存泄漏呢?内存泄漏又有什么影响呢? 在Android程序开发中,当一个对象已经不需要再 ...

  6. WCF开发入门的六个步骤

    在这里我就用一个据于一个简单的场景:服务端为客服端提供获取客户信息的一个接口读取客户信息,来完成WCF开发入门的六个步骤. 1.       定义WCF服务契约 A.      项目引用节点右键添加引 ...

  7. UWP开发入门教程备忘

    UWP-01~03 略~ UWP-04 - 什么是XAML? XAML - 遵循XML语法,XAML实际上是在创建类的实例,并给它们设定属性值,用于定义UI UWP-05 - 类型转换器 类型转换器 ...

  8. web工作流管理系统开发之十六 主子流程参数传递的实现

    在设计流程的时候,如果涉及到子流程,就会有主子流程间传递参数的过程. 例如,将主流程的执行人,传递给子流程,子流程根据主流程的执行人不同,会有不同的处理方式: 又例如,采购流程中,卖方备货处理时,发现 ...

  9. java游戏开发入门(十) -粒子特效

    java游戏开发入门十 - 粒子特效 java游戏开发入门十 - 粒子特效 前言 编码 创建一个粒子发射器,并将粒子发射器添加到实体对象 效果图 完整代码 完整项目 java游戏开发入门十 - 粒子特 ...

最新文章

  1. struts2上传图片的全过程
  2. 【人工智能工程师】掌握这10个项目,秒杀90%面试者!
  3. 〖Android〗从Android Studio转为Eclipse开发项目运行程序闪退的解决方法
  4. python使用缩进作为语法边界一般建议怎样缩进-Python基础自测挑战题
  5. zabbix2.2.3 VMware Vsphere exsi监控配置步骤
  6. 网卡流量监控工具vnstat的使用
  7. python 提取网页正文_一篇文章教会你用Python爬取淘宝海量信息,把淘宝商品整理成一个表格...
  8. 金橙子打标卡labview打标开发没头绪?c#封装成dll后labview调用真香!
  9. IE中对于本地地址不使用代理服务器的选项
  10. 服务器CPU和普通CPU有什么区别?常用的服务器有六大区别
  11. numpy一行转为一列
  12. Redis基础命令(Hash类型)对field进行的操作
  13. Q版京剧脸谱来喽——武生
  14. 在学习thymeleaf中,给function 方法传Controller传递过来的参数,报错:Uncaught SyntaxError: missing ) after argument list
  15. 【2022】较为全面的AlexNet总结
  16. Python 求列表的最长升序子列
  17. python朝圣之路-模块篇
  18. Kaggle: ImageNet Dog Breed Classification (Pytorch)
  19. Category (mathematics)
  20. 女朋友过生日,男子买了一条项链,女友:值不了多少钱

热门文章

  1. dede频道标签channel和频道内容标签channelartlist的调用栏目名的不同方式,如果错误使用标签会发生错误...
  2. php中单引号和双引号的区别,哪个速度更快?为什么?
  3. Failure Groups in ASM
  4. Android TextView 初步学习
  5. 在Flutter中嵌入Native组件的正确姿势
  6. 滴,这周的福利已掉落,镁客君请你免费骑摩拜
  7. 为什么基类的析构函数要声明成虚函数
  8. jsp页面修改成html页面
  9. 最新批量***dedecms|dedecms最新0day
  10. 表达式计算 DataTable/DataRow/DataColumn Expression、JScript CodeDomProvider Eval