On Fri, 28 Mar 2008 00:47:26 +1100, "Bill McCarthy" <Bi**@NOSPAM.com>
wrote:
>Hi Joergen,
Just reading the responses to your post: seems there's a lot of confusion
out there as to what WithEvents and declarative event handling in VB does.
Hopefully this will shed some light upon that for the other folks here.....
When you declare a field as WithEvents, VB actually creates a Property with
that name, and a backing field with the same name prefixed by an
underscore... in this case _tools would be the property name and it would
have a backing field __tools. In the property Set, if __tools is not
nothing, then any events declared declaratively via the Handles statement
will be unwired for the reference. (RemoveHandler), and if the new value is
not nothing, then the events will be wired up.
I took a closer look using Reflector and you are right (which I don't
have to tell you). For others reading this thread, it looks like this:
Private Overridable Property _tools As RepeatTools
Get
Return Me.__tools
End Get
Set(ByVal WithEventsValue As RepeatTools)
If (Not Me.__tools Is Nothing) Then
RemoveHandler Me.__tools.StateChanged, New
StateChangedEventHandler(AddressOf Me._tools_StateChanged)
End If
Me.__tools = WithEventsValue
If (Not Me.__tools Is Nothing) Then
AddHandler Me.__tools.StateChanged, New
StateChangedEventHandler(AddressOf Me._tools_StateChanged)
End If
End Set
End Property
and
"_tools = Nothing"
actually becomes
"Me._tools = Nothing"
which means that the private property setter is called and the
event handler is, in fact, explicitly removed immediately, just by
using "_tools = Nothing".
This also means that removing the WithEvents keyword and adding/
removing event handlers explicitly is not going to make a bit of
difference if everything else is kept the same (i.e. if I keep the
same flow of statements/events).
>So given this, your setting _tools = Nothing will unwire the event handlers.
If however you wrote __tools = Nothing, you would not unwire the event
handlers, and in fact you would prevent VB from being able to unwire. The
extra _ can be an un-doing of the best of code ;)
I can safely say that although I start all my non-public member
variables with an underscore, there are no double underscores
in my source. I would not do such a thing :)
>You also may be experiencing race conditions in that even though you have
attempted to unwire, an event invocation may already be queued. This is
unlikely, but if it is just one extra event immediately after the form is
closed, it can happen.
You hit the nail spot on the head with that last comment.
The form/member destruction does indeed happen in response to a
StateChanged event happening for a reference to the same object
but in another form. That other form then closes the form we are
talking about, leaving a queued event that insists on firing in
limbo.
My original "sentinel" solution takes care of the problem, but
the proper solution would be to take care of the architectural flaw
that allows this to happen.
All my fault.
Regards,
Joergen Bech