【发布时间】:2012-02-07 10:49:09
【问题描述】:
使用 C#、WPF、MVVM、Prism、MEF。 我需要外部效果(我把它从View中调用Dispose())来释放ViewModel中的资源,用在View中。 我使用类似下面的代码:
public class MyViewModel: IDisposable, IMyViewModel, ...
{
private bool disposed = false;
private System.Timers.Timer timer;
public MyViewModel()
{
timer = new System.Timers.Timer();
timer.Interval = 100;
//timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!this.disposed)
{
if(disposing)
{
// Dispose managed resources.
timer.Dispose();
timer = null;
//GC.KeepAlive(timer);
//GC.Collect();
}
disposed = true;
}
}
~MyViewModel()
{
Dispose(false);
}
}
因此,View 和 ViewModel 实例没有被破坏,并且存在内存泄漏。如果删除接口及其方法IDisposable,则View 和ViewModel 删除成功。
我使用 ANTS 内存分析器。在下一张图中,您可以看到来自 DisposableReflecationComposablePart 的三个实例,但必须是一个实例。
我无法理解发生了什么。有什么想法吗?
编辑: 我明白我的陈述解释了问题的链接:http://mef.codeplex.com/wikipage?title=Parts%20Lifetime&referringTitle=Guide
在下面的句子中: 因此,除非满足以下条件之一,否则容器不会保存对其创建的部件的引用:
The part is marked as Shared
The part implements IDisposable
One or more imports is configured to allow recomposition
【问题讨论】:
-
你怎么知道没有IDisposable ViewModel被成功删除了?至少必须停止计时器。无论如何,显式析构函数通常是糟糕的设计,因为它们可能never be called。它不像 C++。
-
是的,这是 C#。我编辑了我的问题并添加了图片。
-
当您观察到泄漏时,即实现了 IDisposable,您是否为 Timer.Elapsed 附加了事件处理程序,或者它仍然被注释掉了?
-
Timer.Elapsed 是否还有注释,你甚至可以删除所有与计时器相关的内容,并且会遇到内存泄漏,如果你从他的方法的最近发现中删除 IDisposable,那么内存泄漏不会是。我可以不用和IDisposable,但原则上我相信通过IDisposable更好,更正确)
-
如果没有针对您的具体问题的解决方案,我认为您误解了IDisposable 的目的:
The primary use of this interface is to release unmanaged resources并且您没有非托管资源。此外,Dispose永远不会自动调用,析构函数也不会自动调用,但只有在对象准备好进行垃圾回收时才会调用。您的方法不是“更正确”,除非您在代码中的某处明确调用 Dispose,否则它根本不正确。
标签: wpf memory prism mef dispose