2009-10-27 48 views
4

我提前道歉;這是一個長期的問題。我試圖儘可能簡化,但仍然比我想看的更囉嗦。VB6集合刪除不會觸發Class_Terminate

在一些遺留代碼中,我們有一個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 

現在,對於每次運行,僕人的class_terminate總是被調用。而且我不能在生產代碼中看到任何應該保持引用集合中的對象的東西。

1.)有沒有什麼辦法強制類在Remove上終止?也就是說,我可以調用Obj.Class_Terminate並確保它每次都能正常工作嗎?

2.)在我的生產代碼(和我的小測試應用程序)上,類標記爲「Instancing - 5 MultiUse」。我意識到這可能是某種線程問題;有沒有一種有效的方式來證明(或反駁)多線程是這個問題的原因 - 我可能會添加某種跟蹤或者可能執行的其他某種測試?


編輯:每低於MarkJ的有見地的評論,我要補充的是,測試上面貼和生產代碼都的ActiveX exe's - 我問多功能使用線程的部分原因。

+2

通過使用hack查看其引用計數,您可以檢查該對象是否仍然在引用後被引用:http://www.vb-helper.com/howto_get_reference_count.html – 2009-10-27 17:20:01

+0

@Pavel,感謝您的鏈接。 – 2009-10-27 18:32:49

回答

3

我們遇到了類似的問題,但是我們可以在哪裏追蹤對象的非終止點,以便下達到我們應用程序中其他位置的實例。

最後,我們不得不寫我們的終止方法是這樣的:

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 確實自動穿線做。其他人將不得不探討這一點的含義,因爲我不熟悉它!

+0

@Ant,我詢問多線程的原因是因爲跟蹤日誌看起來好像我正在執行多個線程。 – 2009-10-27 15:22:29

+0

@Ant,奧諾里奧。一個重要的問題是應用程序是否是ActiveX exe?如果是這樣,那麼VB6 **將自動爲您執行線程,而「多用」選項意味着不同的客戶端可以共享相同的對象。這可能會導致一些併發症。 – MarkJ 2009-10-27 16:04:23

+0

@MarkJ,賓果。是的,我應該在上面的描述中加上這一點。是的,這個應用程序是一個ActiveX exe文件。 – 2009-10-27 17:06:21