为具有COM对象的类编写正确的IDisposable实现

时间:2012-11-28 15:52:58

标签: c# winforms com idisposable

我有一个使用.NET包装器的类用于COM对象,而且它给了我臭名昭着的RCW错误,所以在我的调查中我发现如果我从这个类的终结器中取出Dispose()方法它会修复RCW错误,所以有些东西是错误的,例如对象被处理掉了,但注册的事件仍在闲逛...但是只是删除Dispose()不能成为答案,因为那时谁将释放内存? (我运行了一个内存分析器并确认只是删除Dispose方法会导致20MB的额外非托管内存)

所以我使用Dispose模型的方式应该是错的..这就是我所拥有的:

  private MyCOMobject theCOMobject = null;

    static SuppressFieldCntrlr()
    {
        new SomeCalss();
    }

    ~SuppressFieldCntrlr()
    {
       Dispose(false); 
    }



    private bool disposed = false;

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

    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                theCOMobject.Dispose();
            }

            MethodFoo(false);

            disposed = true;
        }
    }

2 个答案:

答案 0 :(得分:3)

对于COM对象,您需要调用Marshal.ReleaseComObject。 Marshal类位于命名空间System.Runtime.InteropServices

更多信息here

答案 1 :(得分:2)

非托管资源应在if(disposing)部分之外部署。在那里只应处理管理资源。

在COM包装器中:

private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                //Dispose managed resource if any.                   
            }

            //Release the unmanaged resource.

            disposed = true;
        }
    }

并保持Dispose Pattern的实现,因为COM包装器实现了IDisposable。

我不确定ReleaseComObject。显然是not allways recommended。还有Marshal.FinalReleaseComObject方法。另请参阅有关如何包装COM对象的answer

有关如何实施配置模式的详细指南,您可以阅读Joe Duffy撰写的blog entry。它很长但很有用。