【问题标题】:Is my ViewModel actually being disposed of我的 ViewModel 是否真的被处理掉了
【发布时间】:2015-10-23 22:17:57
【问题描述】:

我正在尝试在 mvvm 环境中正确处理视图和视图模型。我在停靠环境中遇到了各种用户控件(本质上是我的视图)及其关联视图模型的一个特殊问题(类似于您在 Visual Studio 中可能看到的那种东西)。

我在这里阅读了无数的帖子、博客和问题,终于找到了我认为有效的东西(确实可能有效,但我就是不明白这个过程)。

在我的视图模型中,我实现了 Idiposable,并在视图中(它被设置为它的数据上下文)我确保视图在卸载时调用它的数据上下文。因此,视图关闭并在其数据上下文(我的视图模型)上调用 dispose,以确保我可以清理任何可能残留并导致内存泄漏(如事件处理程序)的残留物。

一个这样的视图模型在被覆盖的 dispose 子中有以下代码:

   ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not disposedValue Then
            If disposing Then
                ' TODO: dispose managed state (managed objects).
            End If

            ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
            ' 

            ' 
            If mwvm.CanCallDisposeOnErsSubmissionViewModel Then
                mwvm = Nothing
                subEd = Nothing
                retEd = Nothing
            End If

            ' TODO: set large fields to null.
        End If
        Try

            If Not mwvm.CanCallDisposeOnErsSubmissionViewModel Then
                disposedValue = False
            End If
        Catch ex As NullReferenceException
            disposedValue = True
        End Try
        MessageBox.Show("DisposeValue = " & disposedValue.tostring)
    End Sub

此视图模型引用了应用程序主视图模型中的元素(我认为在使用后清理它很重要的原因之一。但是,如果最终用户添加或关闭它所在的停靠站点中的其他窗口(因此需要条件语句)。

现在这可能不太优雅,而且很可能不是正确的方法,但我的问题来自观察以下内容。

当我选择主动关闭视图并且条件语句允许进行清理并将处置的值设置为 true 时,我会认为这意味着视图模型已经很好地真正地关闭和处置的,但是我可以让程序继续运行,然后突然弹出一个消息框,该消息框只能来自上面的处理程序。那么我的模型是否被正确处理掉了,这是正常的行为(大概是垃圾收集器在做它的事情,所以它可以被忽略)还是我的某个地方存在根本错误?

【问题讨论】:

  • 你见过这个问题吗? stackoverflow.com/questions/3258064/…
  • 你的Dispose()方法(来自IDisposable接口的那个,无参数的那个)是怎么实现的?它必须在调用Dispose(true) 之后调用GC.SuppressFinalize(this);。这将阻止 GC 在实际的垃圾回收中调用Dispose()(您无法控制它何时发生,GC 会这样做)。检查 MSDN 以了解 Disposable 模式的正确实现:msdn.microsoft.com/en-us/library/…
  • @Tseng 很棒的电话,谢谢,这正是我想念的。将此标记为答案,不仅这样我可以接受它,而且对于任何想知道它的人来说都是一种简单的方法来发现它。
  • 随意编辑它的 VB.NET 版本来回答,因为 MSDN 没有它的例子

标签: wpf vb.net mvvm idisposable


【解决方案1】:

当使用一次性模式时,您必须在 Dispose() 内调用 GC.SuppressFinalize(this) 以阻止 GC 在完成对象时调用 Dispose() 方法(因为您无法控制 GC 何时执行此操作)

来自 Disposable Pattern 上的 MSDN:

public class DisposableResourceHolder : IDisposable {

    private SafeHandle resource; // handle to a resource

    public DisposableResourceHolder(){
        this.resource = ... // allocates the resource
    }

    public void Dispose(){
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing){
        if (disposing){
            if (resource!= null) resource.Dispose();
        }
    }
}

补充 Tseng 已经说过的内容,但具体与 VB 相关。

如果您在 VB 中的类上实现 IDisposable,则会将以下样板代码添加到该类中:

#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls

' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
    If Not disposedValue Then
        If disposing Then
            ' TODO: dispose managed state (managed objects).
        End If

        ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
        ' TODO: set large fields to null.
    End If
    disposedValue = True
End Sub

' TODO: override Finalize() only if Dispose(disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
'    ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
'    Dispose(False)
'    MyBase.Finalize()
'End Sub

' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
    ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
    Dispose(True)
    ' TODO: uncomment the following line if Finalize() is overridden above.
    ' GC.SuppressFinalize(Me)
End Sub

Stackoverflow 实际上以比 Visual Studio 编辑器更易读的方式突出显示代码。我已将我知道需要处理的位添加到 Overridable Sub Dispose。我已经注意到该部分中取消注释 Ovveride Finalize 部分的评论。我错过的是在实际的 Dispose 方法中继续并取消注释 GC.SuppressFinalize(Me) 行。一个愚蠢的错误,我能提供的唯一借口是绿色的 cmets 把东西融合得太好了。

希望这对其他人有所帮助。

【讨论】:

  • OP 建议进行大量编辑以添加更多信息。
猜你喜欢
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-13
相关资源
最近更新 更多