views:

167

answers:

1

When using a ReadWriteLockSlim for multi-threading support, do I need to EnterWriteLock when using AddHandler?

Here are two examples to help illustrate my point:

AddHandler ClassInstance.Event, New EventHandler(AddressOf Me.Method)

-or-

Me.ReaderWriterLockSlimInstance.EnterWriteLock()
AddHandler ClassInstance.Event, New EventHandler(AddressOf Me.Method)  
Me.ReaderWriterLockSlimInstance.ExitWriteLock()
+2  A: 

It may depend on the event; for example, if you are consuming an event from a dll written in C# via a "field-like event", i.e.

public event EventHandler SomeEvent; // synchronized

(yes I know you asked about VB; I explain this below...)

then this is (per the C# language spec) automatically synchronized, so there are no multi-threading issues (and it helps here that delegates are immutable). However, even in the same library, a non-field-like event might not be synchronized - i.e.

private EventHandler myField;
public event EventHandler SomeEvent { // not synchronized
    add { myField += value; }
    remove { myField -= value; }
}

I know you asked about VB... but you are asking about VB as the comsumer. My point is that it depends on the publisher.

So if you can't control the publisher, then manually synchronizing sounds adviseable if you think that there is a threading risk for this scenario (in most cases, there is no need to synchronize; but if you know this is a threaded area, then synchronizing is sensible).

Also note that a common pattern when raising an event is to take a snapshot:

protected virtual void OnSomeEvent() {
    EventHandler handler = SomeEvent; // assume the "field-like" version
    if(handler!=null) handler(this, EventArgs.Empty);
}

My point here is that it is in theory possible for a subscriber to receive an event even after they think they have unsubscribed, so if extreme cases you might want to handle this manually, perhaps by keeping a flag somewhere (or just exception handling).


As requested, last code fragment in VB (via reflector) for comparison:

Protected Overridable Sub OnSomeEvent()
    Dim handler As EventHandler = Me.SomeEvent
    If (Not handler Is Nothing) Then
        handler.Invoke(Me, EventArgs.Empty)
    End If
End Sub
Marc Gravell
Great post. You raise a very good point. In this instance my program is indeed the producer as well as the consumer. My C# is very rusty at the moment, so is there any chance you could translate the last bit of code you posted into VB.Net?
Charles Y.
I'll translate via reflector and post...
Marc Gravell
Thank you kindly. Again, great answer.
Charles Y.