VB6集合删除不会触发Class_Terminate

Ono*_*cci 5 vb6 collections destructor class

我事先道歉;这是一个很长的问题。我已经尽力简化了,但是仍然比我所想看到的要冗长得多。

在一些旧代码中,我们有一个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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

这是测试工具代码:

Option Explicit
Global g_coll1 As Collection
Public Sub Main()
    Dim a As Master
    Set a = New Master
End Sub
Run Code Online (Sandbox Code Playgroud)

现在,对于每次运行,总是调用Servant的class_terminate。而且我在生产代码中看不到任何应将对象保留在集合中的内容。

1.)有什么方法可以强制类在Remove上终止?也就是说,我可以调用Obj.Class_Terminate并确保它每次都能工作吗?

2.)在我的生产代码(和我的小测试应用程序)上,这些类标记为“ Instancing-5 MultiUse”。我意识到这可能是某种线程问题;有没有一种有效的方法来证明(或反对)多线程是导致此问题的原因-我可能会添加某种跟踪或我可能会执行某种其他测试?


编辑:根据下面MarkJ的有见地的评论,我应该补充一点,上面发布的测试和生产代码都是ActiveX exe的-这是我询问多线程的部分原因。

Ant*_*Ant 4

我们遇到了类似的问题,但是我们可以将对象的非终止追溯到应用程序中其他地方保存的实例。

最后,我们必须这样编写终止方法:

Private Sub Class_Terminate()
    Terminate
End Sub

Public Sub Terminate()
    'Do real termination in here'
End Sub
Run Code Online (Sandbox Code Playgroud)

因此,每当您确实希望终止该类时(即当您调用 g_coll1.Remove 时),您也可以调用Terminate所保留的对象。

我认为你也可以将 Class_Terminate 公开,但在我看来这有点难看。

关于你的观点(2),我认为这不太可能是线程问题,但我想不出一个好的证明/测试。我想您可以考虑的一件非常重要的事情是:您是否在应用程序中手动使用线程?VB6 不会自动执行太多线程...(参见下面的编辑)

[编辑] MarkJ 告诉我们,显然,构建为 ActiveX 应用程序意味着 VB6自动执行线程处理。其他人将不得不探索其含义,因为我不熟悉它!