Event handlers not thread safe? [duplicate] - c#

This question already has answers here:
C# Events and Thread Safety
(15 answers)
Closed 10 years ago.
So i've read around that instead of calling a event directly with
if (SomeEvent != null)
SomeEvent(this, null);
i should be doing
SomeEventHandler temp = SomeEvent;
if (temp != null)
temp(this, null);
Why is this so? How does the second version become thread safe? What is the best practice?

IMO, the other answers miss one key detail - that delegates (and therefore events) are immutable. The significance of this is that subscribing or unsubscribing an event handler doesn't simply append/remove to a list - rather, it replaces the list with a new one with an extra (or one less) item on it.
Since references are atomic, this means that at the point you do:
var handler = SomeEvent;
you now have a rigid instance that cannot change, even if in the next picosecond another thread unsubscribes (causing the actual event field to become null).
So you test for null and invoke it, and all is well. Note of course that there is still the confusing scenario of the event being raised on an object that thinks it unsubscribed a picosecond ago!

Events are really syntactic sugar over a list of delegates. When you invoke the event, this is really iterating over that list and invoking each delegate with the parameters you have passed.
The problem with threads is that they could be adding or removing items from this collection by subscribing/unsubscribing. If they do this while you are iterating the collection this will cause problems (I think an exception is thrown)
The intent is to copy the list before iterating it, so you are protected against changes to the list.
Note: It is however now possible for your listener to be invoked even after you unsubscribed, so you should make sure you handle this in your listener code.

Best practice is the second form. The reason is that another thread might null or alter SomeEvent between the 'if' test and the invocation.

Here is a good write up about .NET events and race conditions with threads. It covers some common scenarios and has some good references in it.
Hope this helps.

Related

Should event firing in C# always be protected by a null check?

This situation seem very interesting to me.
In C# you need to check if there is any listener to the event in a class before firing it.
Assuming event structure of C# is a non-standart(Meaning Microsoft did it) implementation of Observer observable pattern for ease of use.
Why didn't they implement this inside that structure? Is there solid reasons or documentation for this choice.
Is it a necessity do null checking, or am I wrong in my assumption for event structures needing null checks under all circumstances.
This is a more of a curiosity question looking for an answer to this implementation choice by microsoft. Which I hope will lead to further understanding of delegate and event keyword inner workings.
Yes, you must do the null check.
Calling a delegate that is null results in a NullReferenceException.
You might be tempted to intialize all delegates with a non-null, empty event handler. However, that would be far worse than testing for null, in terms of CPU usage, memory usage, and lines of code.
There's a reply to this question in a blog by Eric Gunnerson.
Basically it seems to say that Microsoft thought about changing it, but it would break existing code.
In other words, it was a mistake in the original design for events, but it's too late to fix it.
You can add a default event listener, thus avoiding the null check
public Action<object, EventArgs> SomeEvent = (o, e) => { };
in that way, you can call SomeEvent without checking for null, since it contains a default (empty implementation) listener. Please note that it might hurt performance.

Remove event listener from local variable

Do I have to worry about removing event listeners assigned to local variables?
Consider the following sample:
var zipUtil = new ZipUtil();
zipUtil.ProgressChanged += ZipUtil_ProgressChanged;
I'm creating an instance of the ZipUtil class which is stored as a local variable within a method. Do I have to remove the listener (zipUtil.ProgressChanged -= ZipUtil_ProgressChanged;) before the method terminates or is it okay to skip the step?
No, you don't have to remove that event handling method.
When adding an event handler to an event, a reference from the (object containing the) event to the event handler is created, not the other way round. Once zipUtil goes out of scope, the event handler will not make any difference pertaining to references to zipUtil.
Two lines of code are never enough to make the call accurately. But it is very unlikely you'll need to unsubscribe explicitly. There are two possible problem scenarios:
the class may fire its event at an inopportune time, after your object is disposed for example. That's fairly unlikely in this scenario, surely the ZipUtil class stops raising ProgressChanged events when you stop calling its methods. Not completely out of the question, it could do work on a background thread for example. Not visible from your snippet.
you can have a garbage collection problem due to events. The event delegate keeps an implicit reference to your class object, necessary so it can call ZipUtil_ProgressChanged() method. If it is an instance method, not clear from your snippet. That reference will keep your outer class alive. But not the other way around. Given that the lifetime of the ZipUtil object is restricted to the method and you surely want your outer class to survive at least to the end of the method, this should never be a problem.
High odds that ZipUtil implements IDisposable btw. Do make sure you use the using statement if it does.

Is it OK to always add an empty event handler? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a downside to adding an anonymous empty delegate on event declaration?
The following pattern is quite common when using event handlers (in C#):
public event Action handler;
…
// some method:
if(handler != null) handler();
Are there any downsides of assigning an empty delegate to this event? This would save the if !=null condition everywhere, where the event is fired. Of course, this only applies, when the we cannot guarantee that the event is always assigned a proper delegate.
public event Action handler;
…
// in constructor:
handler += ()=>{};
…
// some method:
handler();
Sure, there's a slight performance hit, but it makes the code much cleaner. What's the best practice in such a case? Any technical disadvantages?
Interesting idea, I've never thought of doing that. The way i do my custom events is i make a OnCustomEventName taking parameters for the event and just do the check in there for null. and call OnCustomEventName from the code wherever i want the event triggered from.
Avoids any performance hits and keeps the operational code cleaner than a 2-line if check every time you want the event fired.
That being said this isn't answering the question about technical disadvantages but more of a best practice when firing events.
example code for threadsafe "On" function.
private void OnCustomEventName()
{
DelegateName localhandler = CustomEventName;
if (localhandler != null)
localhandler();
}
Instead of adding an empty delegate in the constructor, you can wrap the handler in a function which first checks if the handler is null then calls it. The downside of this is if you have a lot of events, you will have a lot of functions that wrap each event.
private void HandlerWrapper()
{
Action localHandler = handler;
if (localHandler != null) handler();
}
I haven't really found any big downsides to do this and generally I prefer it over checking for null. The only issue I cant think of is that it might lead to annoying steps in the code when debugging (i.e.
having to step over the empty delegate whenever stepping into an event).
I think that performance isn't an issue - if application performance degenerates significantly by invoking events, the event should probably not have been there in the first place.

Firing an event in C# with no attatched delegate methods?

I've just encountered a bug in the program I'm writing where an exception was thrown stating an "object reference must be set to an instance of an object". Upon investigation, I found that this exception was thrown when trying to fire an event BUT the event didn't have any delegate methods added to it.
I wanted to check that my understanding was correct that as a developer you shouldn't fire events without first checking that the event doesn't equal null? For example:
if (this.MyEventThatIWantToFire != null)
{
this.MyEventThatIWantToFire();
}
Thanks in advance for the advice/thoughts.
The pattern you've shown is broken in a multi-threaded environment. MyEventThatIWantToFire could become null after the test but before the invocation. Here's a safer approach:
EventHandler handler = MyEventThatIWantToFire;
if (handler != null)
{
handler(...);
}
Note that unless you use some sort of memory barrier, there's no guarantee you'll see the latest set of subscribers, even ignoring the obvious race condition.
But yes, unless you know that it will be non-null, you need to perform a check or use a helper method to do the check for you.
One way of making sure there's always a subscriber is to add a no-op subscriber yourself, e.g.
public event EventHandler MyEventThatIWantToFire = delegate {};
Of course, events don't have to be implemented with simple delegate fields. For example, you could have an event backed by a List<EventHandler> instead, using an empty list to start with. That would be quite unusual though.
An event itself is never null, because the event itself is just a pair of methods (add/remove). See my article about events and delegates for more details.
You shouldn't do it that way - if someone where to remove a listener between the if and the call to the event, you'd get an exception. It is good practise to use it with a local variable:
protected void RaiseEvent()
{
var handler = Event;
if(handler != null)
handler(this, EventArgs.Empty);
}
Of course, this has the disadvantage of maybe calling a listener that already was removed between the creation of the local variable and the call to the handler.
Yes, you should check it for null but the way you're doing it leads to a race condition. It's possible the event may end up being null anyway if someone unsubscribes the last delegate in between your "if" and your event raise. The accepted way to do this is like:
var temp = this.MyEventThatIWantToFire;
if (temp != null) {
this.temp(this, EventArgs.Empty);
}
or alternatively, ensure there's always at least one delegate in the invocation list by declaring your event like this:
public event EventHandler MyEventThatIWantToFire = delegate {};
Make sense?
Yes, your understanding is correct. It's up to you to check the delegate's value before calling it.
Most delegates - which events are - are "multi-cast" delegates. This means that a delegate can manage a list of one or more methods that it will call when activated.
When the delegate evaluates to a null value, there are no registered methods; therefore, there is nothing to call. If it evaluates to something other than a null value, there is at least one method registered. Calling the delegate is an instruction to call all methods it has registered. The methods are called in no guaranteed order.
Using the addition-assignment operator (+=) or addition operator (+) adds a method to the delegate's list of methods. Using the subtraction-assignment operator (-=) or subtraction operator (-) removes a method from the delegate's list of methods.
Also note that the called methods are executed from the caller's thread. This is important if you are using events to update your user interface controls. In this situation, use of your control's InvokeRequired property lets you handle cross-threading calls (using Invoke() or BeginInvoke()) gracefully.
Yes in C# if an event has no delegates, it will be null, so you must check
Yes, you must check whether event is not null. Mostly you encounter protected method that does the check and invokes event, or even constructs event args. Something like this:
public event EventHandler Foo;
protected void OnFoo() {
if (Foo == null)
return;
Foo(this, new EventArgs());
}
This approach also alows your derived classes to invoke (or prevent invoking) the event.

Copying delegates

I was just reading a page on events on MSDN, and I came across a snippet of example code that is puzzling me.
The code in question is this:
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
I understand the intentions of the code, but I fail to see how that particular line is making a copy of anything. All it is doing is copying the reference; it's not actually making a deep copy of the delegate instance. So to that end, it doesn't actually prevent the race condition at all.
Am I missing something obvious here?
Delegates are immutable, so the reference obtained in that code is guaranteed to not change. If a user subscribes or unsubscribes after the null check, a new delegate will be created and set to the event. However, since you have a reference to a completely different object and invoke that, you don't have to worry about it being null.
You are correct; it is copying the reference.
However, delegates are immutable; when you add a handler to an event, a new delegate is created, combining the current handler(s) with the new one, and is then assigned to the field.
The Delegate instance that the field is referencing cannot change, so it does avoid the race condition.
Eric Lippert already covered this in a very detailed post.
This is from MSDN too..
"The invocation list of a delegate is an ordered set of delegates in which each element of the list invokes exactly one of the methods represented by the delegate. An invocation list can contain duplicate methods. During an invocation, methods are invoked in the order in which they appear in the invocation list. A delegate attempts to invoke every method in its invocation list; duplicates are invoked once for each time they appear in the invocation list. Delegates are immutable; once created, the invocation list of a delegate does not change."
if (whatever != null) whatever(); looks like it ensures that whatever is never null when whatever() is called, but it doesn't actually ensure that in a threaded scenario. A different thread can set whatever = null between the check and the call.
Foo temp = whatever;
if (temp != null) temp();
This code removes the possibility of the null dereference, since temp is a local and will therefore never be modified by a different thread. So it does prevent a race condition. It doesn't prevent all the relevant race conditions though. Eric Lippert did a more elaborate discussion of some other problems with the code.

Categories