VB6-Sammlung nicht entfernen Feuer Class_Terminate
-
06-07-2019 - |
Frage
ich im Voraus entschuldigen; dies ist eine lange Frage. Ich habe versucht, so viel zu vereinfachen, wie ich kann, aber es ist immer noch ein bisschen mehr langatmig als ich egal, Sie zu sehen.
In einigem Legacy-Code haben wir eine VB6 Sammlung bekommen. Diese Sammlung fügt Objekte über die .Add Methode und entfernt sie über die .Remove Methode. Doch über Tracing kann ich, dass manchmal sehen, wenn die .Remove aufgerufen wird es scheint, dass die Klasse beenden für das Objekt wird nicht aufgerufen. Aber es ist nicht konsistent; es geschieht nur selten, und ich kann die Umstände, unter denen sie die Klasse nicht nicht isoliert Feuer zu beenden.
Betrachten Sie die folgende Demonstration Code:
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
und
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
und das ist der Test-Harnisch-Code:
Option Explicit
Global g_coll1 As Collection
Public Sub Main()
Dim a As Master
Set a = New Master
End Sub
Nun, für jeden Durchlauf wird der Class_Terminate von Servant immer aufgerufen. Und ich kann nicht alles in der Produktion Code sehen, die das Objekt in der Auflistung verwiesen halten sollte.
1.) Gibt es eine Möglichkeit, die Klasse zu zwingen, auf dem Entfernen beenden? Das heißt, kann ich Obj.Class_Terminate anrufen und sichergestellt wird, jedes Mal arbeiten?
2) Auf dem Produktionscode (und meinen kleinen Test-App) werden die Klassen "Instancing - 5 MultiUse" gekennzeichnet.. Ich weiß, das eine Art von Threading-Problem sein kann; ist es ein effektiver Weg (oder widerlegen), dass Multi-Threading ist die Ursache dieses Problems zu beweisen - eine Art Tracing mich hinzufügen oder eine andere Art von Test könnte ich durchführen könnte
EDIT: Per MarkJ des aufschlussreichen Kommentar unten, soll ich hinzufügen, dass der Test über und den Produktionscode geschrieben ist beide ActiveX exe's - ein Teil des Grundes, warum ich über Mulit-Threading frage
.Lösung
Wir hatten ein ähnliches Problem, aber wo wir die Nicht-Beendigung der Objekte verfolgen konnten auf eine Instanz an anderer Stelle in unserer Anwendung zu sein, nach unten gehalten wird.
Am Ende hatten wir unsere Kündigung Methode wie folgt zu schreiben:
Private Sub Class_Terminate()
Terminate
End Sub
Public Sub Terminate()
'Do real termination in here'
End Sub
Also, wenn Sie wollte wirklich die Klasse beendet werden (das heißt, wenn Sie g_coll1.Remove nennen), können Sie auch Terminate
auf dem gehaltenen Objekt aufrufen.
Ich denke, dass Sie auch Class_Terminate öffentlich machen könnten, aber das ist ein bisschen hässlich meiner Meinung nach.
Re Ihren Punkt (2), halte ich es für sehr unwahrscheinlich ist, ein Threading-Problem zu sein, aber ich kann einen guten Beweis / Test aus der Spitze von meinem Kopf nicht denken. Ich nehme ein sehr recht, was man beachten kann, ist: Verwenden Sie manuell Einfädeln in Ihrer Anwendung? VB6 nicht viel tun Einfädeln automatisch ... (siehe bearbeitet unten)
[ Bearbeiten ] MarkJ uns sagt, dass offenbar als ActiveX-Anwendung erstellen bedeutet, dass VB6 hat automatisch tun Threading. Jemand anderes wird die Tragweite dieses erforschen müssen, da ich nicht mit ihm vertraut war!