Brad Abrams had a recent post about how the usual way of raising an event in C#:
protected virtual void OnMyEvent(EventArgs e)
{
if(MyEvent != null)
{
MyEvent(this, e);
}
}
is not threadsafe. Purely out of curiosity, I wondered if VB handles this the correct way:
protected virtual void OnMyEvent(EventArgs e)
{
EventHandler handler = MyEvent;
if(handler != null)
{
handler(this, e);
}
}
Since VB abstracts this away with the RaiseEvent keyword. Unfortunately it doesn’t seem to, as this code:
Protected Overridable Sub OnMyEvent(ByVal e As EventArgs)
RaiseEvent MyEvent(Me, e)
End Sub
Compiles to this:
.method family newslot virtual instance void OnMyEvent([mscorlib]System.EventArgs e) cil managed
{
// Code Size: 22 byte(s)
.maxstack 8
L_0000: ldarg.0
L_0001: ldfld [mscorlib]System.EventHandler VbConsoleApp.Test::MyEventEvent
L_0006: brfalse.s L_0015
L_0008: ldarg.0
L_0009: ldfld [mscorlib]System.EventHandler VbConsoleApp.Test::MyEventEvent
L_000e: ldarg.0
L_000f: ldarg.1
L_0010: callvirt instance void [mscorlib]System.EventHandler::Invoke(object, [mscorlib]System.EventArgs)
L_0015: ret
}
Which has a race condition—it should store the delegate in a local. Generally, the answer to these questions is “it is fixed in 2005” — so I’m going to just assume that that is the case here.