Silverlight記憶體泄露(六)MEF等Ioc架構引起記憶體泄露-ExportLifetimeContext

來源:互聯網
上載者:User
 對象的建立可以使用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存在多個執行個體,可能出現了記憶體泄露。

經過分析找出發生記憶體泄露的對象圖:

可以看到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) 記憶體泄露都有上下文,只有特定上下文中Managed 程式碼才可能產生記憶體問題。

c)注意由IOC建立的對象生命週期,如果IOC建立的對象由容器管理生命期,可能需要調用IOC提供的相關方法執行對象的銷毀。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.