Thread Safety in VB-2003 Events

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, my answer to all of these questions is “it is fixed in 2005” – so I’m going to just assume that that is the case here.

Tags: , , , ,

One Response to “Thread Safety in VB-2003 Events”

  1. Daniel Moth says:

    Looks like it is :-)
    November CTP:
    Public Event SomeEvent()

    Public Sub IsItFixed()
    RaiseEvent SomeEvent()
    End Sub

    .method public instance void IsItFixed() cil managed
    {
    // Code size 17 (0×11)
    .maxstack 1
    .locals init ([0] class WinAppVB.Form1/SomeEventEventHandler VB$t_ref$S0)
    IL_0000: ldarg.0
    IL_0001: ldfld class WinAppVB.Form1/SomeEventEventHandler WinAppVB.Form1::SomeEventEvent
    IL_0006: stloc.0
    IL_0007: ldloc.0
    IL_0008: brfalse.s IL_0010
    IL_000a: ldloc.0
    IL_000b: callvirt instance void WinAppVB.Form1/SomeEventEventHandler::Invoke()
    IL_0010: ret
    } // end of method Form1::IsItFixed

Leave a Reply