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 ?
Bug: EventHandler is not thread safe.
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.
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.
There is a tiny chance that SomethingHappened
becomes null
after the null check but before the invocation. However, MulticastDelagate
s 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 NullReferenceException
s, 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); }
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With