【问题标题】:How to finalize/destroy class variable如何完成/销毁类变量
【发布时间】:2016-04-02 15:15:51
【问题描述】:

我有一个程序使用某种 Ole 连接来建立与 Cam/cad 软件 Powershape 的连接。它使用类变量与 powershape 建立连接,其属性包含有关打开的模型的信息。

问题是这个连接只有在类变量结束或超出范围时才会结束。

Dim powershapeRoot As New PSAutomation(Delcam.ProductInterface.InstanceReuse.UseExistingInstance)

这在 Subs 中运行良好,因为它超出了范围,但是当您需要来自 powershape 的数据时,此程序需要您执行多次,并且每次重新建立连接可能需要一些时间。所以你可以把它设为全局变量,这样你只需要连接一次。

Dim powershapeRoot As New PSAutomation(Delcam.ProductInterface.InstanceReuse.UseExistingInstance)
Powershapeglobal = powershapeRoot

但是现在变量只有在程序关闭后才会超出范围。我尝试使用:

Powershapeglobal.dispose
Powershapeglobal = nothing

这些没有帮助,连接似乎仍然存在,因为变量仍然存在?如何永久销毁变量?

【问题讨论】:

  • 在 VBA 中,您可以使用“Set”关键字将对象变量设置为“Nothing”
  • 除了正确释放 COM 对象以使指针不再存在之外,您还应该为 GC 释放对象。 Andrew Whitechapel 在他的书中很好地介绍了这一点,有关释放 COM 对象部分的相关摘录:msdn.microsoft.com/en-us/library/office/…
  • 这听起来像是您所依赖的 PSAutomation 类中的一个错误。正确设计和实现的类会为此使用 IDisposable 模式。

标签: vb.net ole


【解决方案1】:

在 .NET 中,当 .NET 变量超出范围时,非托管资源不会被销毁。当垃圾收集器将它们从内存中删除时,它们就会被销毁,这是垃圾收集器认为有必要的时候。这称为“非确定性最终确定”,因为您,开发人员无法确定对象最终确定的确切时间。

为确保在使用完外部资源后清理它们,请调用相关对象的 Dispose() 方法:

  Dim powershapeRoot As New PSAutomation(Delcam.ProductInterface.InstanceReuse.UseExistingInstance)

而且,当你想释放连接时:

  powershapeRoot.Dispose();

或者,要让 Dispose 自动发生,请使用 .NET“Using”语句:

 Using powershapeRoot As New PSAutomation(Delcam.ProductInterface.InstanceReuse.UseExistingInstance)



 End Using ' Dispose is called automatically here

现在,对于 COM 对象,流程还有一个步骤,您必须显式调用 ReleaseComObject() 方法,如下所示:

 System.Marshall.ReleaseComObject(powershapeRoot);

然后调用 Dispose() 之后。但是,仅当您明确引用了 COM 程序集时才需要这样做。使用 OleDB 连接,调用 Dispose 就足够了。

https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject(v=vs.110).aspx

【讨论】: