我在其中有五个方法我的.NET 3.5的C#WinForms应用程序已经一类。 每种方法都使用不同组的C ++ COM接口。 我使用Marshal.FinalReleaseCOMObject
清理这些COM对象。 此代码工作正常在这个.NET平台没有任何问题。 但是,当我提出这个申请到.NET 4.0,我开始在这些方法中一条线,我投一个变量从一个收到此错误ICOMInterface1
到ICOMInterface2
,即:
ICOMInterface1 myVar= obj as ICOMInterface2;
不能使用已从与其基础RCW分开COM对象。
如果我删除其中使用我行Marshal.FinalReleaseCOMObject
,我没有得到这个错误。
我缺少的是在这里吗? 而且我怎么收拾从内存上的.NET 4.0平台,这些非托管COM对象?
简单的答案是永远不会使用Marshal.FinalReleaseComObject
除非你绝对必须。 如果你这样做,有一个你必须遵循一些额外的规则。
当一个COM对象在.NET中使用时,运行时创建了所谓的“RCW”或“运行时可调用包装”该对象。 这是RCW只是一个普通的对象,持有对象上的COM引用。 当这个对象被垃圾回收,它将调用的IUnknown ::发行()的COM对象,如你所期望的。 这意味着,除非你的COM对象要求的最后一个版本()是在时间上非常某一时刻完成的,只是让垃圾收集照顾它。 许多COM对象属于这种情况,所以绝对验证您必须管理调用release()仔细。
所以,当你调用FinalReleaseComObject,那基本上递减RCW有COM对象,直到它击中零和RCW然后释放COM对象的引用。 在这一点上,这个RCW现在zombied,以及任何使用它会给你见过例外。 在CLR(默认)只创造了任何潜在的COM对象的单个RCW,所以这意味着,如果你使用的COM API返回的同一对象两次,它只是将有一个单一的RCW。 调用FinalReleaseComObjectwould意味着突然说RCW的所有使用敬酒。
只有这样,才能保证你有一个独特的Marshal.GetUniqueObjectForIUnknown,防止任何RCW共享。 但是就像我刚才所说,在大多数COM API本时并不需要摆在首位的事,所以干脆不要做它。
保罗·哈灵顿写了一个很好的博客帖子大约[最后] ReleaseComObject的,它的弊端。 这是说,除非必要,只会伤害你的危险武器。 既然你问这个问题,我怀疑你实际上并不需要在所有调用它。 :-)
文章来源: “COM object that has been separated from its underlying RCW cannot be used” with .NET 4.0