【问题标题】:Writing the correct IDisposable implementation for classes with COM objects为具有 COM 对象的类编写正确的 IDisposable 实现
【发布时间】:2012-11-16 13:00:08
【问题描述】:

我有一个对 COM 对象使用 .NET 包装器的类,它给了我那个臭名昭著的 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;
        }
    }

【问题讨论】:

  • 什么是“RCW 错误”? RCW 代表 Runtime Callable Wrapper,它只是一个自动生成的包装 COM 对象的 .NET 类。因此,RCW 不是错误,我无法推断出您遇到了什么特定的与 RCW 相关的错误。

标签: c# winforms com idisposable


【解决方案1】:

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

更多信息here

【讨论】:

  • 我用这个 Marshal 方法替换了终结器方法中的 Dispose(false) 并且仍然得到 RCW。
【解决方案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 模式实现不变,因为 COM 包装器实现了 IDisposable。

我不确定ReleaseComObject。显然是not allways recommended。还有Marshal.FinalReleaseComObject 方法。还可以查看answer,了解如何包装 COM 对象。

有关如何实现 dispose 模式的详细指南,您可以阅读 Joe Duffy 撰写的 blog entry。篇幅较长,但很有帮助。

【讨论】:

  • 好的 试过了...不,现在它甚至比以前更快地崩溃并出现 RCW 错误。
猜你喜欢
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
相关资源
最近更新 更多