我的ViewModel实际上是否被处理掉了

时间:2015-10-23 08:43:00

标签: wpf vb.net mvvm idisposable

我正试图理解在mvvm环境中正确处理视图和视图模型。我遇到了一个特殊的问题,包括各种用户控件(实际上是我的观点)以及它们在对接环境中的相关视图模型(类似于你在visual studio中可能看到的那种)。

我在这里阅读了无数的帖子,博客和问题,最后发现了一些我认为有用的东西(事实上它很可能但我只是不理解这个过程)。

在我的viewmodel中,我实现了Idiposable并在视图中(它被设置为datacontext)我确保视图在卸载时调用其datacontext上的dispose。因此,视图关闭并在其datacontext(我的viewmodel)上调用dispose,以确保我可以清除任何可能会挂起并导致内存泄漏的事件处理程序。

一个这样的viewmodel在重写的dispose sub中有以下代码:

   ' 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

这个viewmodel引用了应用程序的mainviewmodel中的元素(为什么我觉得在使用后清理它是很重要的原因之一。但是如果最终用户添加或者重新绘制数据上下文的视图会重新绘制关闭它所在的docksite中的其他窗口(因此需要条件语句)。

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

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

1 个答案:

答案 0 :(得分:1)

使用一次性模式时,必须在GC.SuppressFinalize(this)内调用Dispose()以禁止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,则以下Boiler版代码将添加到该类中:

#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)行。我这个愚蠢的错误唯一可以提供的借口是绿色评论将事情融合在一起。

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