我在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对象?
答案 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>
此外,如果对象在发生时引用了用户控件,则可能无法卸载包含它的用户表单。