惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
L
LINUX DO - 最新话题
Recorded Future
Recorded Future
月光博客
月光博客
博客园 - 【当耐特】
博客园 - 叶小钗
宝玉的分享
宝玉的分享
量子位
雷峰网
雷峰网
博客园 - 三生石上(FineUI控件)
The Cloudflare Blog
Vercel News
Vercel News
L
LangChain Blog
B
Blog
Y
Y Combinator Blog
爱范儿
爱范儿
GbyAI
GbyAI
S
Security @ Cisco Blogs
T
The Blog of Author Tim Ferriss
A
About on SuperTechFans
博客园 - Franky
P
Palo Alto Networks Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
云风的 BLOG
云风的 BLOG
C
Cisco Blogs
Scott Helme
Scott Helme
I
Intezer
T
The Exploit Database - CXSecurity.com
MyScale Blog
MyScale Blog
T
Tor Project blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Troy Hunt's Blog
N
News and Events Feed by Topic
大猫的无限游戏
大猫的无限游戏
F
Fortinet All Blogs
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
S
Security Affairs
Cyberwarzone
Cyberwarzone
PCI Perspectives
PCI Perspectives
小众软件
小众软件
D
DataBreaches.Net
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Know Your Adversary
Know Your Adversary
Forbes - Security
Forbes - Security
S
Securelist
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
The Last Watchdog
The Last Watchdog

博客园 - 思无邪

Silverlight内存泄露(八)样式 Silverlight内存泄露(七)Command Silverlight内存泄露(六)MEF等Ioc框架引起内存泄露-ExportLifetimeContext Silverlight内存泄露(五)MEF等Ioc框架引起内存泄露-PartCreationPolicy Silverlight内存泄露(四)解决内存泄露 Silverlight内存泄露(二)检测内存泄露 从火狐放弃依据特性更新版本说起 Silverlight内存泄露(一)序 Silverlight IReader阅读器第二版 silverlight阅读器——面向领域的浏览器(二)——Silverlight阅读器架构 silverlight阅读器——起源面向领域的浏览器——概念 silverlight异步陷阱(二)循环 silverlight 异步陷阱(一)不能Remove事件处理程序 IReader Silverlight电子阅读器介绍开源项目 silverlight在线阅读器(二):为silverlight增加gb2312编码 silverlight在线阅读器(一):介绍 新建立一个类似于CuteEditor的项目,希望有人参加。发布一个测试版本的dll 从控件开发的角度看几个editor控件,Freetextbox,radtoolbar,abouteditor,cuteeditor 想做一个关于word解析和HtmlEditor的项目,希望有人加入 cuteEditor6.0的破解方式与Cuteeditor6.0的脚本调试
Silverlight内存泄露(二)解决内存泄露之Dispose误用
思无邪 · 2011-04-12 · via 博客园 - 思无邪

按顺序第二篇应该是”如何检测SIlverlight内存泄露”,但这一系列都是解决实际问题的日志,有些检测结果没有被保存下来,不可能为了写这些文章,而重现bug。想到哪就写到哪了。

看到许多文章在解决事件为被注销引起内存泄露时,通过在Dispose中注销事件,以释放资源,这可能会出现未预料的问题。

Dispose模式介绍

参考:Effective C# - 条款18:实现标准的Dispose模式

要点:

通过实现IDisposable接口,你写成了两件事:第一就是提供了一个机制来及时的释放所有占用的托管资源,另一个就是你提供了一个标准的模式让用户来释放非托管资源。这是十分重要的,当你在你的类型上实现了IDisposable接口以后,用户就可以避免析构时的损失。你的类就成了.Net社 区中表现相当良好的成员。

但在你创建的机制中还是存在一些漏洞。如何让一个派生类清理自己的资源,同时还可以让基类很好的再做资源清理呢?(译注:因为调用Dispose方法时, 必须调用基类的Dispose,当然是在基类有这个方法时。但前面说过,我们只有一个标记来标识对象是否处理过,不管先调用那个,总得有一个方法不能处理这个标记,而这就存在隐患) 如果基类重载了析构函数,或者自己添加实现了IDisposable接口,而这些方法又都是必须调用基类的方法的;否则,基类无法恰当的释放资源。同样,析构和处理共享了一些相同的职责:几乎可以肯定你是复制了析构方法和处理方法之间的代码。正如你会在原则26中学到的,重载接口的方法根本没有如你所期望的那样工作。Dispose标准模式中的第三个方法,通过一个受保护的辅助性虚函数,制造出它们的常规任务并且挂接到派生类来释放资源。基类包含接口的核心代码, 派生类提供的Dispose()虚函数或者析构函数来负责清理资源

Dispose可能存在的问题

Dispose是Object就有的方法,任何代码都有可能调用,并且子类应该调用基类的Dispose。从中可看出:

1. Dispose是.Net固有的方法,任何代码都可能调用

2. Dispose是自上而下执行的,基类到子类。

这表明Dispose是不可控的,其他代码很可能会调用这个方法。

MVVM light最初也依赖Dispose释放资源,但在新版本中已经使用ICleanUp接口释放资源,就是由于Dispose太不可控了。但为了兼容前版本,Dispose仍然有效。

Dispose引起问题的例子例子

[ViewModelExport(typeof(ChapterViewModel), "Chapter")]

[PartCreationPolicy(CreationPolicy.NonShared)]

public class ChapterViewModel:NavViewModel

{

ChapterService service 

= new ChapterService();public C

[ViewModelExport(

typeof(ChapterViewModel), "Chapter")]

[PartCreationPolicy(CreationPolicy.NonShared)]

public class ChapterViewModel:NavViewModel

{

ChapterService service 

= new ChapterService();public ChapterViewModel()

{

service.Loaded 

+= new EventHandler<AsyncEventArgs<object>>(service_Loaded);

}

void service_Loaded(object sender, AsyncEventArgs<object> arg)

{

}

public void Dispose()

{

service.Loaded 

-= new EventHandler<AsyncEventArgs<object>>(service_Loaded);

}

}

hapterViewModel()

{

service.Loaded 

+= new EventHandler<AsyncEventArgs<object>>(service_Loaded);

}

void service_Loaded(object sender, AsyncEventArgs<object> arg)

{

}

public void Dispose()

{

service.Loaded 

-= new EventHandler<AsyncEventArgs<object>>(service_Loaded);

}

}


按照预想Dispose会注销事件,避免内存泄露,但运行时会发现service_Loaded可能不被执行,原因是 Dispose()被第三方程序调用了,而这些调用可能很隐蔽。

在这个程序里,下面的代码调用了Dispose,并且不易被发现。


var viewModelFactory = viewModelMapping.CreateExport();

viewModel 

= viewModelFactory.Value as IViewModel;

viewModelFactory.Dispose();

解决方式

通过其他方式注销事件,比如显式的接口、弱引用、匿名方法,在事件引起的内存泄露的文章中会详述几种解决方式。

在MVVM Light的cleanup注销事件


public override void Cleanup()

{

service.Loaded 

-= new EventHandler<AsyncEventArgs<object>>(service_Loaded);

Messenger.Default.Unregister(

this);base.Cleanup();

}

MVVM Light的问题

按上面的方式本应该解决问题,但是service_Loaded 仍有可能不被执行。原来Mvvm Light为了保持和上一版本的兼容性在Dispose方法中调用了Cleanup。

重载Dispose


protected override void Dispose(bool disposing)

{

//,覆盖基类
禁止调用cleanup

}

结论

1. 尽量不要用Dispose释放托管资源,而使用自己的接口。

2. Dispose中绝对不应该调用其他方法,像MVVM light中调用cleanup,就会导致问题。

3.第三方框架引来的代码复杂性应该被考虑。