我正在围绕DirectSound编写托管包装器。 (这是一个简单的部分包装器,解决了我的具体问题,仅此而已。请不要告诉我关于NAudio或其他什么。)包装IDirectSound8的托管类是否应该是IDisposable,为什么?关于IDirectSoundBuffer8的相同问题。
答案 0 :(得分:1)
技术上:是的。实际上:没有。 IDirectSound8是一个COM接口,它们非常方便地用.NET包装,带有互操作库。 RCW。 RCW管理底层COM coclass对象的引用计数。 RCW 不实现IDisposable,即使它非常依赖于非托管资源。
之所以没有,是因为几乎不可能正确实现IDisposable。 COM coclass实现多个接口,创建一个添加引用计数。在处置安全之前,您必须100%确定所有这些接口指针已不再使用。这很难做到,这些指针以意想不到的方式创建。与使用其中一个接口的索引属性一样,中间接口指针在代码中永远不可见。
这不是一个真正的问题,垃圾收集器负责引用计数,终结器完成工作。只是需要更长时间才能释放对象。标准GC行为。不幸的是,进程外COM服务器具有可观察到的副作用,当代码停止使用接口时,当进程没有从TaskMgr进程列表中消失时,程序员往往会感到恼火。很多很多“Excel / Word不会在这里和论坛上退出”。
如果你想要实现它,那么你可以通过在Dispose()实现中调用Marshal.FinalReleaseComObject()来实现它。只要注意显着增加的失败风险,错误地调用该错误会导致很难诊断失败。与删除本机代码中的对象并且仍然具有指向它的指针完全不同。如果它实际上是一个“重”对象,必须立即释放,那么GC.Collect()+ GC.WaitForPendingFinalizers()也可以完成工作,并且错误的风险要小得多。当然还有副作用。