Silverlight内存泄露(六)MEF等Ioc框架引起内存泄露-ExportLifetimeContext

 对象的创建可以使用new,也可以使用IOC架如:castle、MEF等,IOC创建的对象的生命周期,可能IOC负责管理,使用框架的开发者如果不弄清楚可能会造成内存泄露问题。

这些内存泄露问题并不是IOC框架的bug,只是开发者使用不当或者不注意造成的内存泄露问题。

以MEF为例说明我碰到的两种内存泄露问题。

内存泄露系列阅读提示:

一摸一样的对象图,有时候我们可以认为它是内存泄露,有时候又认为它不是内存泄露,这一切只是由于上下文不同,这一系列文章中ANTS Memoery Profle截图都是有特定上下文,单独看完全没有意义。如何确定是内存泄露?可以参考前面的文章。

对象以图的形式存在,Ants Memory Profile为了分析方便把这些图处理为树,让我们可以把注意力集中到分析的对象。但我们必须明白内存中对象关系构成图,也就是说ANTS的树状图只是内存中对象分布的一个局部,分析内存泄露时必须有全局观念,需要相关的几张图一起看,即使一张图也要整体看,这样才能分析内存泄露问题。

由于看一张图没什么意义,如果把多张图都贴出来,这文章就太难写了,即使多张图都贴出来,也不一定能表达清楚,分析内存泄露最重要的是经验。接下来的几篇会减少甚至不用ANTS图。

ExportLifetimeContext使用不当造成内存泄露

ExportLifetimeContext 需要调用Dispose方法释放由MEF管理的对象,否则对象不会被释放。

MSDN:

Disposing of a ExportLifetimeContext(Of T) object calls the referenced method to release its associated export.

Call Dispose when you are finished using the ExportLifetimeContext(Of T). The Dispose method leaves the ExportLifetimeContext(Of T) in an unusable state. After calling Dispose, you must release all references to the ExportLifetimeContext(Of T) so the garbage collector can reclaim the memory that theExportLifetimeContext(Of T) was occupying. 

可以看到ViewModel存在多个实例,可能出现了内存泄露。

clip_image002

经过分析找出发生内存泄露的对象图:

clip_image004

可以看到MEF的DisposableReflectionComposablePart一直保持着ViewModel的引用,造成不能释放ViewModel。

MVVM使用自定义导航,代码: 

[Export]
public   class  CompositionNavigationContentLoader : INavigationContentLoader
{
public  CompositionNavigationContentLoader()
{
}
[ImportMany(
typeof (IView))]
public  IEnumerable < ExportFactory < IView, IViewMetadata >>  ViewExports {  get set ; }
[ImportMany(
typeof (IViewModel),RequiredCreationPolicy  =  CreationPolicy.Any)]
public  List < ExportFactory < IViewModel, IViewModelMetadata >>  ViewModelExports {  get set ; }
[ImportMany(
" lazy " typeof (IViewModel), RequiredCreationPolicy  =  CreationPolicy.Any)]
public  List < Lazy < IViewModel, IViewModelMetadata >>  LazyViewModelExports {  get set ; }
public  IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback,  object  asyncState)
{
var viewModelMapping 
=  ViewModelExports.FirstOrDefault(o  =>  o.Metadata.Key.Equals(relativeUri.Host, StringComparison.OrdinalIgnoreCase));
// ViewModel
var viewModelFactory  =  viewModelMapping.CreateExport();
viewModel 
=  viewModelFactory.Value  as IViewModel;
viewModelFactory.Dispose(); // 释放对象
// View
var viewFactory  =  viewMapping.CreateExport();
view 
=  viewFactory.Value  as  Control;
viewFactory.Dispose(); 
// 释放对象
// 绑定、导航
view.DataContext  =  viewModel;
var values 
=  viewModelMapping.Metadata.GetArgumentValues(targetUri);
viewModel.OnNavigated(values); 

}

 

如果不加上viewModelFactory.Dispose();

对象MEF创建的对象不会被回收,VIew、ViewModel及其引用的资源都一直保持到程序关闭。 

结论

a) 不要盲目使用第三方框架。

b) 内存泄露都有上下文,只有特定上下文中托管代码才可能产生内存问题。

c)注意由IOC创建的对象生命周期,如果IOC创建的对象由容器管理生命期,可能需要调用IOC提供的相关方法执行对象的销毁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值