【问题标题】:VB6 Collection Remove Doesn't Fire Class_TerminateVB6 集合删除不会触发 Class_Terminate
【发布时间】:2010-12-10 12:29:05
【问题描述】:

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

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

【问题讨论】:

标签: vb6 collections class destructor


【解决方案1】:

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

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

【讨论】:

  • @Ant,我之所以询问多线程是因为跟踪日志看起来好像我正在执行多个线程。
  • @Ant, Onorio。一个重要的问题是应用程序是否是 ActiveX exe?如果是这样,那么 VB6 自动为您执行线程,并且“MultiUse”选项意味着不同的客户端可以共享相同的对象。这可能会导致一些并发症。
  • @MarkJ,宾果游戏。是的,我应该将其添加到我上面的描述中。是的,有问题的应用程序是 ActiveX exe。
  • @MarkJ:啊哈我不知道。有趣。
  • @Onorio:如果您使用 CreateObject 函数从 Ax EXE 创建实例,VB6 将执行线程化。运算符 New 将使用“快捷方式”并且总是在当前线程上创建对象。因此,在您的示例案例中线程不是问题。
猜你喜欢
  • 1970-01-01
  • 2014-02-27
  • 1970-01-01
  • 2019-03-31
  • 1970-01-01
  • 2015-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多