COM对象清理

时间:2010-11-13 01:04:07

标签: c# vba dll garbage-collection com-interop

我在excel中的VBA脚本中实例化一个COM对象,如C#dll中所定义。我实例化的C#类有一个执行垃圾收集的终结器,特别是它引用的其他MS Office对象,我应该看到它在任务管理器中出现和消失。事实上,单元测试表明,在调用dll时会出现Office进程,并在完成时消失。

当从VBA调用dll时,我注意到在VBA函数结束后进程保持打开状态,即对象在被调用后没有清理,这使我相信VBA不会释放COM对象。

我的功能看起来像这样:

Function Raz(inp As String)
 Dim o: Set o = CreateObject("foo.bar")
 o.InputFields.FirstInput = inp
 o.Update
 Raz = o.OutputFields.FirstOutput
End Function

我在函数末尾添加了以下行以解决问题:

set o = Nothing

但是,我的COM进程中的资源在执行和完成VBA脚本后仍然存在。如何在不手动创建dispose调用的情况下从VBA中垃圾收集COM对象?

3 个答案:

答案 0 :(得分:4)

COM将在最后一次引用消失后将进程保留在内存中一段时间​​,以防万一你想要在不久之后创建另一个需要相同进程的对象。

理论是流程创建非常缓慢且昂贵,并且您可能无意中编写了一个循环或执行此操作的内容:

 While 1=1

      Set a = CreateObject(...)
      ' Later
      Set a = Nothing

 Wend

你不希望Windows在循环中无休止地杀死和启动进程。

最终它们会消失。

答案 1 :(得分:1)

在VBA中,释放对象的命令是

Set o = Nothing

答案 2 :(得分:1)

您对创建的对象 Raz 函数返回值有一个 弱引用 ,它维护对象实例。

变量o是自动的,并且当函数返回时,引用的对象自动设置为空,但是您将值分配给 Raz 并且可能分配给客户端代码,因此实例值不会在函数返回时处理。 / p>

此外,如果对象在发生时引用了用户控件,则可能无法卸载包含它的用户表单