0

我的班级正在使用 COM 资源,并且我从 IDisposable 继承了它。为了清理非托管资源,我有调用 Marshall.ReleaseCOMObject() 方法的 Dispose() 方法......所以我的问题是我们还需要 Destructor 方法(Finalizer)吗?释放COM资源?当我确实有 finalzier 方法并在其中调用 Marshal 或 Dispose 时,我会收到一个 RCW 错误,当我删除 finalizer 方法时,我不会再收到 RCW 错误但是如果我查看内存分析器,我可以看到非托管资源每次打开包含此 COM 资源的表单时,内存都会不断增加...所以看起来它没有清理它?那么在 C# 应用程序中清理 COM 资源的正确方法是什么?

我将使用我很快拥有的一些代码示例来更新问题。

谢谢。

private MyCOMobject theCOMobject = null;

static SuppressFieldCntrlr()
{
    new SomeCalss();
}


private bool disposed = false;

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

private void Dispose(bool disposing)
{
    if (!this.disposed)
    {
        if (disposing)
        {
           //nothing in here, is it just for Managed Resources? 
        }

        Marshal.ReleaseComObject(this);
        MethodFoo(false);

        disposed = true;
    }
}
4

3 回答 3

2

如果您的类不直接拥有非托管资源,并且您知道没有派生类将直接拥有非托管资源(例如,因为您的类是密封的,所以您的类是内部的),那么您不需要终结器。

就我个人而言,即使不是绝对必要的,我也会使用终结器来实现标准模式。主要是为了最不意外的原则,并且因为其他人可能决定在将来解封它或允许派生类具有非托管资源。

另请注意,COM 对象是托管资源,因此您应该在 disposing 为 true 时调用 ReleaseComObject:

private void Dispose(bool disposing)
{
    if (!this.disposed)
    {
        if (disposing)
        {
            // Dispose managed resources
            Marshal.ReleaseComObject(this);
        }
        // If you directly own unmanaged resources, they'd be freed here

        disposed = true;
    }
}
于 2012-11-28T17:26:47.657 回答
2

您正在封装一个托管对象,而不是非托管对象。您没有 P/invoke'd 来获取 Win32 文件句柄、设备上下文或类似的东西;相反,您获得了对托管对象(RCW)的引用。你应该把你的电话放在你Marshal.ReleaseComObject的方法if (disposing)部分Dispose(bool)

RCW 本身将有一个终结器,它将负责IUnknown->Release()记录实际的 COM 对象,因此如果您还没有ReleaseComObject在需要进行终结的地方调用,那么 COM 对象将被垃圾收集器删除。

于 2012-11-28T17:27:59.823 回答
0

如果我们有非托管资源,强烈建议使用终结器。在这种情况下:

~ClassName
{
    Dispose(false);
}
于 2012-11-28T17:19:05.267 回答