VB6 集合删除不会触发 Class_Terminate

标签 vb6 collections class destructor

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

在一些遗留代码中,我们有一个 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——这是我询问多线程的部分原因。

最佳答案

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

最后,我们不得不像这样编写我们的 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 会自动执行线程处理。其他人将不得不探索这的含义,因为我不熟悉它!

关于VB6 集合删除不会触发 Class_Terminate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1631321/

相关文章:

python - 在调用类方法时被迫传递一个对象本身——我做错了吗?

logging - VB6-如何在启动应用程序时在VB6中创建日志文件

c# - 使用非 VB6 对象在 VS2008 中调试 VB6

vb6 - VB 中自动化错误的处理

string - Visual Basic 6.0 中的无效限定符错误

c# - 如何将 List<T> 对象项目正确存储到 List<T> 的另一个实例而不影响其单个项目值 - C#

java - 使用 map 修改对象列表的有效方法

java - 在流上使用 Collections.toMap() 时如何保持 List 的迭代顺序?

java - 如何在不使用集合的情况下在java中制作列表?

java - 有没有办法缩短这段重复的代码? (添加 JPanel 组件)