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

  内存泄漏的概念我这里就不说了,之前《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();
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注意一下就可以了。

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

  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. Android内存管理(13)常见产生内存泄漏的原因

    1.集合类泄漏 集合类如果仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用.如果这个集合类是全局性的变量 (比如类中的静态属性,全局性的 map 等即有静态引用或 final 一直指向它), ...

  2. UWP开发入门(六)——对多设备不同分辨率显示效果的讨论

    本篇不涉及具体代码,而是把实际开发UWP APP的过程中,遇到的不同设备,不同分辨率显示效果差异的问题进行讨论.希望能够抛砖引玉,和各位擦出一些火花. 蜀黍我目前是在做一套牛逼的UWP APP啦,目标 ...

  3. UWP开发入门(十)——通过继承来扩展ListView

    本篇之所以起这样一个名字,是因为重点并非如何自定义控件,不涉及创建CustomControl和UserControl使用的Template和XAML概念.而是通过继承的方法来扩展一个现有的类,在继承的 ...

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

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

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

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

  6. UWP开发入门系列笔记之(一):UWP初览

    标签: 随着微软Build2015带来的好消息,Win10正式版发布的日子已经离我们越来越近了,我们也终于欣喜地看到:一个统一的Windows平台对于开发人员来说充满了吸引力,这局棋下的好大的说--于 ...

  7. Android开发 |常见的内存泄漏问题及解决办法

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

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

    android中一个对象已经不需要了,但是其他对象还持有他的引用,导致他不能回收,导致这个对象暂存在内存中,这样内存泄漏就出现了.   内存泄漏出现多了,会是应用占用过多的没存,当占用的内存超过了系统 ...

  9. UWP开发入门(四)——自定义CommandBar

    各位好,再次回到UWP开发入门系列,刚回归可能有些不适应,所以今天我们讲个简单的,自定义CommandBar,说通俗点就是自定义类似AppBarButton的东西,然后扔到CommandBar中使用. ...

随机推荐

  1. RTTI的实现(vc)--转载

    RTTI (Run Time Type info) 这个神奇的东西用于存储类的相关信息,用于在运行时识别类对象的信息.C++ 里面只记录的类的名字和类的继承关系链.使得编译成二进制的代码,对象可以知道 ...

  2. (转)投影矩阵的推导(Deriving Projection Matrices)

    转自:http://blog.csdn.net/gggg_ggg/article/details/45969499 本文乃<投影矩阵的推导>译文,原文地址为: http://www.cod ...

  3. 将 Book-Crossing Dataset 书籍推荐算法中 CVS 格式测试数据集导入到MySQL数据库

    本文内容 最近看<写给程序员的数据挖掘指南>,研究推荐算法,书中的测试数据集是 Book-Crossing Dataset 提供的亚马逊用户对书籍评分的真实数据.推荐大家看本书,写得不错, ...

  4. Swift编程语言SequenceType协议中的一些比较有用的接口

    在Swift编程语言中,大部分容器类(比如Array.Dictionary)都实现了SequenceType协议.SequenceType协议中有不少有趣且简便的方法可用来实现我们不少实际需求.这里将 ...

  5. wordpress图片水印插件DX-Watermark

    DX-Watermark是一款功能齐全的wordpress图片水印插件,可以自动给上传的图片添加文本或者图片水印. 后台截图: 文本水印: 图片水印: 选项说明: 类型:可选择文本或图片水印两种类型, ...

  6. C# Use Pop3Client to read gmail

    host = "pop.gmail.com" user = "xxxxx@gmail.com" password = "xxxx" port ...

  7. Debug Assertion Failed! Expression: _pFirstBlock == pHead

    点击Abort之后,查看调用栈,发现异常在函数return时被时产生,进一步看是vector的析构函数被调用时产生,以前没开发过C++项目,没什么经验,这个错误让我很困惑,第一,我电脑上并没有f盘:第 ...

  8. Base64的编码转换方式

    下面,详细介绍Base64的编码转换方式. 所谓Base64,就是说选出64个字符----小写字母a-z.大写字母A-Z.数字0-9.符号"+"."/"(再加上 ...

  9. CISA 信息系统审计知识点 [第二章. IT治理和管理 ]

    第二章.  IT治理和管理 1.  IT治理.管理.安全和控制框架及标准.指南和实践 IT治理是董事会和执行管理层的职责. IT治理的关键因素:保持与业务的战略一致,引导业务价值的实现. IT治理关注 ...

  10. WPF中如何用代码触发按钮Click处理

    btnOk.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));