Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raise event thread safely - best practice [duplicate]

In order to raise an event we use a method OnEventName like this:

protected virtual void OnSomethingHappened(EventArgs e)  {     EventHandler handler = SomethingHappened;     if (handler != null)      {         handler(this, e);     } } 

But what is the difference with this one ?

protected virtual void OnSomethingHappened(EventArgs e)  {     if (SomethingHappened!= null)      {         SomethingHappened(this, e);     } } 

Apparently the first is thread-safe, but why and how ?

It's not necessary to start a new thread ?

like image 260
Jérémie Bertrand Avatar asked Sep 08 '10 14:09

Jérémie Bertrand


People also ask

Are event handlers thread safe?

Bug: EventHandler is not thread safe.

Which is the best place to subscribe event handler to an event?

To subscribe to events by using the Visual Studio IDEOn top of the Properties window, click the Events icon. Double-click the event that you want to create, for example the Load event. Visual C# creates an empty event handler method and adds it to your code. Alternatively you can add the code manually in Code view.

How do you make a method thread safe in C#?

So friends this just an example to make you understand why it is necessary to make thread as Thread Safe in Csharp. In order to make a thread as thread safe there are some thread synchronization techniques like Monitor/Lock, Mutex, Semaphore and SemaphoreSlim using these techniques we can achieve Thread Safety.


2 Answers

There is a tiny chance that SomethingHappened becomes null after the null check but before the invocation. However, MulticastDelagates are immutable, so if you first assign a variable, null check against the variable and invoke through it, you are safe from that scenario (self plug: I wrote a blog post about this a while ago).

There is a back side of the coin though; if you use the temp variable approach, your code is protected against NullReferenceExceptions, but it could be that the event will invoke event listeners after they have been detached from the event. That is just something to deal with in the most graceful way possible.

In order to get around this I have an extension method that I sometimes use:

public static class EventHandlerExtensions {     public static void SafeInvoke<T>(this EventHandler<T> evt, object sender, T e) where T : EventArgs     {         if (evt != null)         {             evt(sender, e);         }     } } 

Using that method, you can invoke the events like this:

protected void OnSomeEvent(EventArgs e) {     SomeEvent.SafeInvoke(this, e); } 
like image 179
Fredrik Mörk Avatar answered Oct 02 '22 23:10

Fredrik Mörk


Since C# 6.0 you can use monadic Null-conditional operator ?. to check for null and raise events in easy and thread-safe way.

SomethingHappened?.Invoke(this, args); 

It’s thread-safe because it evaluates the left-hand side only once, and keeps it in a temporary variable. You can read more here in part titled Null-conditional operators.

Update: Actually Update 2 for Visual Studio 2015 now contains refactoring to simplify delegate invocations that will end up with exactly this type of notation. You can read about it in this announcement.

like image 31
Krzysztof Branicki Avatar answered Oct 02 '22 23:10

Krzysztof Branicki