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

推荐订阅源

Vercel News
Vercel News
Recorded Future
Recorded Future
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The GitHub Blog
The GitHub Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Microsoft Azure Blog
Microsoft Azure Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
M
MIT News - Artificial intelligence
云风的 BLOG
云风的 BLOG
Y
Y Combinator Blog
N
News | PayPal Newsroom
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Help Net Security
Help Net Security
博客园 - Franky
SecWiki News
SecWiki News
Recent Announcements
Recent Announcements
T
Troy Hunt's Blog
The Register - Security
The Register - Security
The Last Watchdog
The Last Watchdog
Webroot Blog
Webroot Blog
S
Security Affairs
博客园 - 司徒正美
S
Schneier on Security
I
InfoQ
博客园_首页
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
Threat Research - Cisco Blogs
Forbes - Security
Forbes - Security
腾讯CDC
N
Netflix TechBlog - Medium
N
News and Events Feed by Topic
Cloudbric
Cloudbric
T
The Exploit Database - CXSecurity.com
P
Proofpoint News Feed
A
About on SuperTechFans
Engineering at Meta
Engineering at Meta
Recent Commits to openclaw:main
Recent Commits to openclaw:main
B
Blog
V
Vulnerabilities – Threatpost
C
Check Point Blog
Google DeepMind News
Google DeepMind News
Google Online Security Blog
Google Online Security Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
C
Cisco Blogs
Schneier on Security
Schneier on Security
O
OpenAI News
K
Kaspersky official blog

博客园 - 思无邪

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.第三方框架引来的代码复杂性应该被考虑。