【问题标题】:Memory leak with IDisposable in ViewModel, why?ViewModel 中 IDisposable 的内存泄漏,为什么?
【发布时间】: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


【解决方案1】:

请参阅my question here 以获得可能对您有所帮助的答案。

我遇到了类似的情况,最终使用了自定义界面,比如ICleanup,而不是IDisposable,以避免让 MEF 引用我的观点。

我认为这是 MEF 设计中的一个非常大的缺陷。我认为他们至少会让每个部分自己决定是否应该通过使用某个属性或通过实现接口来保留对它的引用......

【讨论】:

  • 由于某种原因我没有看到这个问题。我必须这样做并开始使用他的界面(代替 IDisposable)。
猜你喜欢
  • 2011-12-23
  • 1970-01-01
  • 2011-10-25
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2011-03-05
  • 2015-08-04
相关资源
最近更新 更多