何时使用ReleaseComObject和FinalReleaseComObject?

27
1个回答

29

FinalReleaseComObject有其优点,它能够更快地使程序崩溃。“COM对象已分离其基础运行时可调用包装(RCW), 不能再使用”是CLR告诉您自己处理COM引用计数而不是交给CLR处理是一个错误的提示。您可能会遇到各种问题,您不能仅仅依靠在开发机器上运行成功来验证代码是否正确。请确保在将代码部署到客户机器上时实现良好的错误报告。

该方法的优点是只有一个地方的代码有错,那就是FinalReleaseComObject调用。如果使用ReleaseComObject,情况会变得模糊不清得多。因为这种错误会被忽略一段时间,直到CLR调用最终的IUnknown::Release()并销毁对象时才导致程序崩溃,距离错误的ReleaseComObject调用非常远。但这是末日场景,更有可能的结果是该调用根本没有任何影响,因为您可能会错过难以发现的操作,例如mumble["foo"],这是一个很难被察觉到的索引器引用。

我的建议很明显:不要这样做。您正在与一个永远不会犯错的机器竞争,只是它执行起来略慢一些。这里有一个非常好的“现实报告”,可以在此处找到。“悄无声息的刺客”部分最为相关。

如果有必要让COM服务器立即退出,那么让计算机处理将所有引用计数归零的操作。使用GC.Collect()方法即可。但请记住,如果您想在调试时也能起作用,必须正确地调用该方法。在使用COM对象的同一方法中使用它是行不通的,详情见此答案。请将其放置在调用方法中。


2
你是在建议根本不释放对象吗? - C. Ross
3
好的,也许那并不是很清楚。移除所有Marshal类的调用。当你注意到任何差异时再回来。 - Hans Passant
5
我已经删除了所有Marshal类调用,发现代码更加稳定,RCW和COM错误更少。谢谢!我之前只是按照我正在使用的SAP SDK的建议添加了这些调用。 - Booji Boy
3
@HansPassant的建议(不要使用FinalReleaseCOM)在您PInvoke非托管代码的情况下是否也适用? - probably at the beach
3
不,PInvoke与调用COM接口方法无关。使用[DllImport]属性进行PInvoke,它没有与之关联的COM接口指针。 - Hans Passant
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接