Custom event whine (1 Viewer)

Really? This is what we are complaining about. I mean come on. If I had 50 forms I figure I could do this manually for all forms in less than 5-10 minutes. I am sure far quicker than for you to write the post. If I had 10,000 forms I could write code in extensibility to do this.
1. Check if Close form method exists
2. If not add a close form method
3. Add code to set the event raiser to nothing
I assume in form you use the same variable to hold the event raiser instance.
Yes, really - that is what I am complaining about. It's not the amount of effort to necessary to get this working, it's the fact that ANY effort is necessary at all. Local variables are supposed to get destroyed when their containing form closes, period. Stuff is supposed to work the way the manuals say it works. I should not have to deal with inventing workarounds for random bugs because the guys as MS can't be bothered to test their stuff properly.

What if it was numeric variables, instead of a WithEvents class variable? Or string variables? Or string variables beginning with a certain letter? Or arrays? Or only two-dimensional arrays, but one dimension or greater than two worked okay? Sure - easy to set them all to zero, nothing, empty or whatever on exit - if you know they have that problem, and if you remember it every time. But would you also think it was fine, because it was 'easy' to fix?

Yes, I do use the same name in every form. And my standardizing all these forms to be as identical as possible made it simple to put together a three-line sub with the single action of setting the WithEvents variable to Nothing and slap it into every code module. Grand total of maybe 15 seconds to write the sub and 30 seconds to install it everywhere, compile and save, once I realized what I needed to do. Not the point - the point is that I should not have to do this. This is a bug in the VBA runtime system, and it is not a trivial one, even if the workaround for it is.
 
This is a bug in the VBA runtime system, and it is not a trivial one, even if the workaround for it is.
Access includes a method where you can report issues to MS. I can assure you that they read the messages. I can't guarantee they will fix it though.
 
Yes, really - that is what I am complaining about. It's not the amount of effort to necessary to get this working, it's the fact that ANY effort is necessary at all. Local variables are supposed to get destroyed when their containing form closes, period. Stuff is supposed to work the way the manuals say it works. I should not have to deal with inventing workarounds for random bugs because the guys as MS can't be bothered to test their stuff properly.

What if it was numeric variables, instead of a WithEvents class variable? Or string variables? Or string variables beginning with a certain letter? Or arrays? Or only two-dimensional arrays, but one dimension or greater than two worked okay? Sure - easy to set them all to zero, nothing, empty or whatever on exit - if you know they have that problem, and if you remember it every time. But would you also think it was fine, because it was 'easy' to fix?

Yes, I do use the same name in every form. And my standardizing all these forms to be as identical as possible made it simple to put together a three-line sub with the single action of setting the WithEvents variable to Nothing and slap it into every code module. Grand total of maybe 15 seconds to write the sub and 30 seconds to install it everywhere, compile and save, once I realized what I needed to do. Not the point - the point is that I should not have to do this. This is a bug in the VBA runtime system, and it is not a trivial one, even if the workaround for it is.
Perhaps it won't help here, but the Access team does not own VBA. That means they have little control over how it works, although they must work closely with the team that does own VBA. Certainly, they're not in a position to make such a fundamental change.

Moreover, it's no secret that Microsoft would just as soon be done with supporting VBA at all. The so-called New Outlook, with the spiffy JavaScript stuff, is a shiny example of that, I'm afraid.

I don't think Pat is being pessimistic, therefore, in suggesting that nothing much is going to change in VBA, regardless of whether you report this to Microsoft.
 
Certainly, they're not in a position to make such a fundamental change.
I think the change would be in the hidden Access form code which the Access team does own. Who knows, maybe this behavior was by design. Maybe they had some reason to not destroy the object.

@pdanes Access has always had a problem with cleanup and memory leaks. Maybe this causes bloat or a memory leak. I would report the problem, even send them the database if they ask so they can see what is happening and the one line of code that fixes it. This will probably never affect another application so they certainly won't change it for you but if it causes other bad things, they may fix it.
 
This is a bug in the VBA runtime system, and it is not a trivial one, even if the workaround for it is.
The triviality of the solution IS the triviality of the problem.
 
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.
 

Attachments

The triviality of the solution IS the triviality of the problem.
That is a ridiculous statement. The seriousness of a problem and the difficulty of a workaround have nothing to do with each other.
 
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.
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.

I'll check that and let you know. Thanks for the tip.
 
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.
 
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.
 
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.
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.
 
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...
Code:
Private Sub Form_Unload(Cancel As Integer)
    Set lvw_ = Nothing
    Set pop_ = Nothing
    Set del_ = Nothing
End Sub
This same subform declares del_ as...
Code:
Private WithEvents del_ As Lib.cSysEvent
... which I use like a global event delegate, so objects can send each other messages without knowing anything about each other.
That class has this code...
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
... 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.

Hopefully that makes sense,
 
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...
Code:
Private Sub Form_Unload(Cancel As Integer)
    Set lvw_ = Nothing
    Set pop_ = Nothing
    Set del_ = Nothing
End Sub
This same subform declares del_ as...
Code:
Private WithEvents del_ As Lib.cSysEvent
... which I use like a global event delegate, so objects can send each other messages without knowing anything about each other.
That class has this code...
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
... 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.

Hopefully that makes sense,
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.
 

Users who are viewing this thread

Back
Top Bottom