When the form instance is destroyed (reference counter -> 0). This does not have to be after closing if a reference to the form still exists.Local variables are supposed to get destroyed when their containing form closes, period.
When the form instance is destroyed (reference counter -> 0). This does not have to be after closing if a reference to the form still exists.Local variables are supposed to get destroyed when their containing form closes, period.
That is a ridiculous statement. The seriousness of a problem and the difficulty of a workaround have nothing to do with each other.The triviality of the solution IS the triviality of the problem.
Oh, I wonder if that's it. I do have variables referring to the forms, and I don't think I clear those when I close the forms.When the form instance is destroyed (reference counter -> 0). This does not have to be after closing if a reference to the form still exists.
Nope - that wasn't it. I have global variable pointers to the parent form and each subform, set in each of the form/subform's Load events, and I explicity set all three to nothing in the Close event of the parent form. But despite that, this multiple instancing of the WithEvents variable was happening. It only stopped when I set that WithEvents variable to nothing in each subform's Close event.When the form instance is destroyed (reference counter -> 0). This does not have to be after closing if a reference to the form still exists.
I guess that makes a certain amount of sense, but I did release the variables. Although, now that I think about it, I release them in the parent form's Close event. I wonder if I need to release them directly in the subform. Maybe letting the subform close while the variable still points to it locks something up, so that a subsequent release of that variable no longer relinquishes all its contents.A WithEvents variable must hold a list of references to objects in which it is declared, since it needs to call back to them when it raises an event. If you close a form that contains a WithEvents variable that has another pointer to it, it doesn't go out of scope, nor does its reference list. This is a race condition. The Form can't release the WithEvents variable, so the WithEvents variable can't release the Form, and the Form can't go out of scope. This is a memory leak.
Nope, that wasn't it either. Commented out the line setting the WithEvents variable to nothing, just to confirm the problem still exists. It does. But even when I release the global variable pointing to each subform directly in the subform's Close event, this unwanted accumulation of instances happens. I don't even have to do anything in the form. Simply opening it is enough to cause this stacking. The ONLY way I have found so far to cure it is to release the WithEvents variable directly. If I do that, it works properly, If I do anything else, it does not.A WithEvents variable must hold a list of references to objects in which it is declared, since it needs to call back to them when it raises an event. If you close a form that contains a WithEvents variable that has another pointer to it, it doesn't go out of scope, nor does its reference list. This is a race condition. The Form can't release the WithEvents variable, so the WithEvents variable can't release the Form, and the Form can't go out of scope. This is a memory leak.
Private Sub Form_Unload(Cancel As Integer)
Set lvw_ = Nothing
Set pop_ = Nothing
Set del_ = Nothing
End Sub
Private WithEvents del_ As Lib.cSysEvent
Public Event SysEvent(Sender As Object, Args As IEventArgs)
Public Sub RaiseSysEvent(Sender As Object, Args As IEventArgs)
RaiseEvent SysEvent(Sender, Args)
End Sub
It does, thank you, and it appears to be the exact same problem as I encountered, in a most similar arrangement - a central class for events, form/subform construct raising events, and complete disassociation of objects raising events from objects reacting to events. Setting the WithEvents variable to Nothing has worked for me in the subforms' Close event. I will continue to try odd bits, like you mention the UnLoad event, to see if I can add any insight to the exact circumstances, maybe even the cause, but for now, I have a clear and functional workaround, so I can experiment at my leisure. I appreciate the insights you have offered.I have actually only seen this happen if the WithEvents variable is declared in a SubForm (and only if that variable still has another valid reference to it, like the global event raising class you describe). I had exactly this symptom, that the main form had closed, but multiple instances of the subform continued to handle the WithEvents variable's events, one subform instance being added to the list each time I opened the main form.
What worked for me was to explicitly set the WithEvents variable to Nothing in the SubForm's Form_Unload() event handler. I think Form_Close() is too late, because I don't think you have programmatic access to any of the Form's resources in Form_Close(), like, try to Debug.Print the name of a control.
This is my code on the subform, very simple...
This same subform declares del_ as...Code:Private Sub Form_Unload(Cancel As Integer) Set lvw_ = Nothing Set pop_ = Nothing Set del_ = Nothing End Sub
... which I use like a global event delegate, so objects can send each other messages without knowing anything about each other.Code:Private WithEvents del_ As Lib.cSysEvent
That class has this code...
... so all it can do is raise one event, and consumers who subscribe to it can determine if an event is for them based on the type of IEventArgs, which is an empty, or marker interface.Code:Public Event SysEvent(Sender As Object, Args As IEventArgs) Public Sub RaiseSysEvent(Sender As Object, Args As IEventArgs) RaiseEvent SysEvent(Sender, Args) End Sub
Hopefully that makes sense,
Still does that to me sometimes. No warning, no error - just quits. Biggest culprit currently is custom right-click menus on comboboxes. Sometimes they work, sometimes not. Decompile and C&R sometimes helps, sometimes not. Some of them I've had to abandon completely, convenient and pretty though they are, because Access just won't deal with them.Lol, when I was a boy... (from too many years of Clifford the big red dog)
When I was a boy this stuff would just close Access down without warning. Completely shut down. They fixed that. I have always preached CLEAN UP BEHIND YOURSELF. Whether you should have to can be argued till the cows come home but in the end this kind of gotcha irritations mostly go away if you CLEAN UP BEHIND YOURSELF.
And yea, I get that just having a place to vent helps. BTW I actually built rather elaborate code to register every class I instantiated, removing it when it was cleaned up. It helped me track what was instantiated, when, and in what order.