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