我正在做单元测试。
我的解决方案中有 2 个项目 1 是库项目,1 是测试项目。图书馆项目有一些 com 组件。测试项目是测试库项目中的功能。这些库函数正在使用这些 com 对象。
第一个单元测试成功执行,但是当我尝试按顺序执行 2 个单元测试时,在第二个单元测试中,当我尝试访问这些 com 对象时,我收到错误“无法使用已与其底层 RCW 分离的 COM 对象”。
我正在做单元测试。
我的解决方案中有 2 个项目 1 是库项目,1 是测试项目。图书馆项目有一些 com 组件。测试项目是测试库项目中的功能。这些库函数正在使用这些 com 对象。
第一个单元测试成功执行,但是当我尝试按顺序执行 2 个单元测试时,在第二个单元测试中,当我尝试访问这些 com 对象时,我收到错误“无法使用已与其底层 RCW 分离的 COM 对象”。
这意味着有人使用Marshal.ReleaseComObject
不正确,或者更糟糕的是,使用Marshal.FinalReleaseComObject
. 第一个单元测试通过这种相关的副作用影响第二个单元测试,可能是在拆卸方法中。解决此问题的第一步是准确找出导致该异常的对象/访问/位置。
发生这种情况是因为在已释放 COM 对象(COM ref-count 设置为 0)的 RCW 上调用方法,这意味着ReleaseComObject
已调用太多次或FinalReleaseComObject
根本没有调用。
如果您拥有一个 RCW 对象(已将其“带入 CLR”),并且它的生命周期已到,ReleaseComObject
则可以(将变量设置null
为也可以避免再次使用它)。使用FinalReleaseComObject
通常永远不会好,因为它不可能正确地跟踪生命周期。诀窍是要记住,单个 RCW 对象表示COM 对象已“带入 CLR”并具有内部(非 COM)计数器的一次或多次。
在许多情况下,GC 将在其终结器运行时正确处理 RCW 清理。并且当时 RCW 不是强可达的,因此无法生成异常。在需要严格控制COM 生命周期的情况下,使用显式ReleaseComObject
[仅] 是必需的/有用的(考虑 COM 对象的“共享” )。在处理 Microsoft Office 产品的加载项开发时,这很重要:)Dispose
.NET 和 COM 互操作性中还有其他详细信息(在我的回答中):从 .NET 客户端释放 COM和一篇反文章ReleaseComObject 被认为是危险的
快乐编码。