VB6集合删除不会触发Class_Terminate
-
06-07-2019 - |
题
在一些遗留代码中,我们有一个VB6集合。此集合通过.Add方法添加对象,并通过.Remove方法删除它们。但是,通过跟踪我可以看到,有时当调用.Remove时,似乎没有调用该对象的类终止。但它并不一致;它很少发生,我无法隔离它未能解雇类终止的情况。
请考虑以下演示代码:
Option Explicit
Private Const maxServants As Integer = 15
Private Const className As String = "Master"
Private Sub Class_Initialize()
Debug.Print className & " class constructor "
Set g_coll1 = New Collection
Dim i As Integer
For i = 1 To maxServants
Dim m_servant As Servant
Set m_servant = New Servant
m_servant.InstanceNo = i
g_coll1.Add Item:=m_servant, Key:=CStr(i)
Debug.Print "Adding servant " & m_servant.InstanceNo
Next
End Sub
Private Sub Class_Terminate()
Dim i As Integer
For i = maxServants To 1 Step -1
g_coll1.Remove (CStr(i))
Next
Debug.Print className & " class terminator "
Set g_coll1 = Nothing
Exit Sub
End Sub
和
Option Explicit
Private Const className As String = "Servant"
Private m_instanceNo As Integer
Private Sub Class_Initialize()
m_instanceNo = 0
Debug.Print className & " class constructor "
End Sub
Public Property Get InstanceNo() As Integer
InstanceNo = m_instanceNo
End Property
Public Property Let InstanceNo(newInstanceNo As Integer)
m_instanceNo = newInstanceNo
End Property
Private Sub Class_Terminate()
Debug.Print className & " class terminator for " & CStr(Me.InstanceNo)
End Sub
这是测试工具代码:
Option Explicit
Global g_coll1 As Collection
Public Sub Main()
Dim a As Master
Set a = New Master
End Sub
现在,对于每次运行,始终调用Servant的class_terminate。而且我在生产代码中看不到任何应该将对象保留在引用的集合中的内容。
1。)有没有办法强制类终止取消?也就是说,我可以调用Obj.Class_Terminate并确保它每次都能正常工作吗?
2.。)在我的生产代码(和我的小测试应用程序)上,类被标记为“Instancing - 5 MultiUse”。我意识到这可能是某种线程问题;有没有一种有效的方法来证明(或反驳)多线程是导致这个问题的原因 - 我可能会添加一些跟踪或者我可能会执行的其他类型的测试?
编辑:根据下面MarkJ的见解,我应该补充一点,上面发布的测试和生产代码都是ActiveX exe文件 - 这也是我询问多线程的部分原因。
解决方案
我们遇到了类似的问题,但是我们可以在哪里跟踪对象的非终止,直到我们的应用程序中其他地方的实例。
最后,我们必须编写这样的终止方法:
Private Sub Class_Terminate()
Terminate
End Sub
Public Sub Terminate()
'Do real termination in here'
End Sub
所以每当你真的希望终止类时(即当你调用g_coll1.Remove时),你也可以在被保持的对象上调用 Terminate
。
我认为你也可以公开Class_Terminate,但在我看来这有点难看。
重申你的观点(2),我认为这不太可能成为一个线程问题,但我想不出一个好的证明/测试。我想你可以考虑的一个非常重要的事情是:你在应用程序中手动使用线程吗? VB6没有自动执行太多线程...(参见下面的编辑)
[编辑] MarkJ告诉我们,显然构建为ActiveX应用程序意味着VB6 会自动执行线程化。其他人将不得不探讨这个含义,因为我不熟悉它!