I've come across this before but never actually considered the thread safe aspect of it until I was reading a thread on the altdotnet group.
A lot of people invoke events like this:
if (someEvent != null)
{
someEvent(this, someEventArgs);
}
This is partially right and in a single threaded environment will work fine but this code is not actually thread safe. If you imagine that the event is basically just a list of delegates and if you consider that your application may be using multiple threads then it is possible that between you performing the check for null and actually invoking the event the list may have changed. For example there may have been one delegate in there at the time of the check which is not there when the invoke occurs causing an exception to be thrown.
A thread safe way to invoke events is to make a copy of the delegate list and use that. In the past I've always done this anyway even if I'm in a single threaded app partially out of habit and partially because it means I can potentially introduce threading later without having to worry about my events. This would look like this:
EventHandler temp = someEvent;
if (temp != null)
{
temp(this, someEventArgs);
}
Now obviously this is much better as it is safe but we've not got several lines of code just to raise an event and its always been something that I know I and others have felt is slightly klunky.
An alternative method is to assign an empty delegate to the event in the declaration. This now means that you never have to worry about the event being null and so you remove the need for the check. The event declaration looks like this:
public event EventHandler SomeEvent = delegate {};
And to raise the event you simply do this:
SomeEvent(this, someEventArgs);
Just one line of code replaces everything we had to do above. This is thread safe because we don't have to do a null check before we invoke the event.
Of course this comes at a cost. The null check route is faster as if there is no one listening to the event we don't take any action. You also have to bear in mind that if the event is on a class which will have a lot of instances at runtime then there is a memory overhead of having that extra delegate. A tiny overhead, but if we are talking about hundreds of thousands of instances of a class then that will add up quite a bit.
However I don't believe most enterprise apps will really have performance requirements that rules out this style, the difference in speed will almost certainly be unnoticeable and if we do need a particular type to have so many instances then we can just use the null check style. In .Net there is a general rules that performance shouldn't be an issue until it becomes an issue, we should concentrate on readability and maintainability when coding and if we find performance problems once we are done then get some metrics and refactor to solve the problem. I think this is a very good example where we can improve code readability.