5

我提前道歉;这是一个很长的问题。我已经尽可能地简化了,但它仍然比我想看到的要冗长一些。

在一些遗留代码中,我们有一个 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.) 有什么方法可以强制类在 Remove 上终止?也就是说,我可以调用 Obj.Class_Terminate 并确保它每次都能正常工作吗?

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


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

4

1 回答 1

4

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

最后,我们必须像这样编写 Termination 方法:

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自动执行线程。其他人将不得不探索这个的含义,因为我不熟悉它!

于 2009-10-27T15:05:42.113 回答