【发布时间】:2018-08-14 22:57:40
【问题描述】:
我有一个 COM 可见的 C# 程序集。它又与第 3 方 COM 应用程序通信。我的问题是,当我从 VBA 释放对我的 C# 程序集的引用时,C# 程序集保持第 3 方应用程序处于打开状态。
' Call assembly from VBA
Dim asm : Set asm = CreateObject("MyCSharpAssembly")
' Get a managed object exposed by the assembly
' managedObject communicates with a 3-rd party COM application
Dim managedObject : Set managedObject = asm.GetManagedObject()
' When I release managedObject from VBA, the 3rd party application stays open.
Set managedObject = Nothing
我尝试在 managedObject 中实现 IDisposable 模式并显式释放 COM 对象。这行得通,但我仍然必须从 VBA 显式调用 Dispose 方法。仅将 managedObject 的引用设置为 Nothing 是不够的。 VBA 编码人员很容易忘记这一点,他们可能认为将对象设置为 Nothing 就足够了。
有什么方法可以从 C# 的角度进行编码,还是我必须坚持使用显式的 Dispose?
【问题讨论】:
-
您的 VBA 代码使 C# 对象有资格进行垃圾回收。如果发生这种情况,也会最终确定它用来与第 3 方组件通信的 RCW。 “如果发生这种情况”子句是问题,垃圾收集器仅在需要时运行。例如,您必须帮助另一个 C# 对象,该对象公开了一个调用 GC.Collect() 的方法。
-
this answer 中有一个绝望的方法,不知道会造成多大的麻烦。这样做的典型问题是很难找到所有的接口引用,而缺少其中一个是不可调试的失败鲸鱼。否则 GC.Collect 比 Marshal.ReleaseComObject 更好的原因。
-
感谢您的意见,汉斯。已经阅读了这个问题,包括你建议的文章(和相关文章)一两天了,我的脑袋嗡嗡作响。他们的很多内容都超出了我的专业水平。但是,从您的第一条评论中,我了解到在 VBA 中取消引用对象时不会调用析构函数(终结器) - 这取决于 GC。这并不能解决我的问题,但让我相信我并不完全疯了。我现在会坚持使用后明确“关闭”对象的要求。