COM对象清理

3
我正在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个回答

4

在最后一次引用消失后,COM会将过程保留在内存中一段时间,以防您很快要创建另一个需要相同进程的对象。

理论上,进程的创建非常缓慢且昂贵,您可能会无意间编写循环或其他操作,例如:

 While 1=1

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

 Wend

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

最终它们会消失。


2

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

变量o是自动的,当函数返回时,引用对象会自动设置为无效,但你正在赋值给Raz,可能还赋值给客户端代码,因此实例化的值在函数返回时不会被释放。

此外,如果该对象引用了一个用户控件,你可能无法卸载包含它的用户窗体


1
在VBA中释放对象的命令是:
Set o = Nothing

所以我尝试了那个方法,但最终器仍然没有被调用。最后我实现了IDisposable并手动释放资源,结合set o = Nothing这一行...我不知道是否所有东西都被释放了,但至少dispose释放了大的东西。 - tbischel
你能否详细解释一下你是如何实现IDisposable的呢?我写了一个Visual Foxpro 9 COM服务器,也遇到了同样的问题。谢谢。 - Caltor
@Caltor,你需要使用“@tbischel”来引起他的注意(只有第一个“@”有效,所以你仍然需要自己完成)。 - Lance Roberts
@Lance-Roberts 感谢您的 @ 提示。我认为这已经成为一个无意义的问题了,因为根据 https://dev59.com/kFvUa4cB1Zd3GeqPpQjQ - Caltor

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