I frequently hear/read the following advice:
Always make a copy of an event before you check it for null and fire it. This will eliminate a potential problem with threading where the event becomes null at the location right between where you check for null and where you fire the event:
// Copy the event delegate before checking/calling
EventHandler copy = TheEvent;
if (copy != null)
copy(this, EventArgs.Empty); // Call any handlers on the copied list
Updated: I thought from reading about optimizations that this might also require the event member to be volatile, but Jon Skeet states in his answer that the CLR doesn't optimize away the copy.
But meanwhile, in order for this issue to even occur, another thread must have done something like this:
// Better delist from event - don't want our handler called from now on:
otherObject.TheEvent -= OnTheEvent;
// Good, now we can be certain that OnTheEvent will not run...
The actual sequence might be this mixture:
// Copy the event delegate before checking/calling
EventHandler copy = TheEvent;
// Better delist from event - don't want our handler called from now on:
otherObject.TheEvent -= OnTheEvent;
// Good, now we can be certain that OnTheEvent will not run...
if (copy != null)
copy(this, EventArgs.Empty); // Call any handlers on the copied list
The point being that OnTheEvent runs after the author has unsubscribed, and yet they just unsubscribed specifically to avoid that happening. Surely what is really needed is a custom event implementation with appropriate synchronisation in the add and remove accessors. And in addition there is the problem of possible deadlocks if a lock is held while an event is fired.
So is this Cargo Cult Programming? It seems that way - a lot of people must be taking this step to protect their code from multiple threads, when in reality it seems to me that events require much more care than this before they can be used as part of a multi-threaded design. Consequently, people who are not taking that additional care might as well ignore this advice - it simply isn't an issue for single-threaded programs, and in fact, given the absence of volatile in most online example code, the advice may be having no effect at all.
(And isn't it a lot simpler to just assign the empty delegate { } on the member declaration so that you never need to check for null in the first place?)
Updated: In case it wasn't clear, I did grasp the intention of the advice - to avoid a null reference exception under all circumstances. My point is that this particular null reference exception can only occur if another thread is delisting from the event, and the only reason for doing that is to ensure that no further calls will be received via that event, which clearly is NOT achieved by this technique. You'd be concealing a race condition - it would be better to reveal it! That null exception helps to detect an abuse of your component. If you want your component to be protected from abuse, you could follow the example of WPF - store the thread ID in your constructor and then throw an exception if another thread tries to interact directly with your component. Or else implement a truly thread-safe component (not an easy task).
So I contend that merely doing this copy/check idiom is cargo cult programming, adding mess and noise to your code. To actually protect against other threads requires a lot more work.
Update in response to Eric Lippert's blog posts:
So there's a major thing I'd missed about event handlers: "event handlers are required to be robust in the face of being called even after the event has been unsubscribed", and obviously therefore we only need to care about the possibility of the event delegate being null. Is that requirement on event handlers documented anywhere?
And so: "There are other ways to solve this problem; for example, initializing the handler to have an empty action that is never removed. But doing a null check is the standard pattern."
So the one remaining fragment of my question is, why is explicit-null-check the "standard pattern"? The alternative, assigning the empty delegate, requires only = delegate {} to be added to the event declaration, and this eliminates those little piles of stinky ceremony from every place where the event is raised. It would be easy to make sure that the empty delegate is cheap to instantiate. Or am I still missing something?
Surely it must be that (as Jon Skeet suggested) this is just .NET 1.x advice that hasn't died out, as it should have done in 2005?
UPDATE
As of C# 6, the answer to this question is:
SomeEvent?.Invoke(this, e);
The JIT isn't allowed to perform the optimization you're talking about in the first part, because of the condition. I know this was raised as a spectre a while ago, but it's not valid. (I checked it with either Joe Duffy or Vance Morrison a while ago; I can't remember which.)
Without the volatile modifier it's possible that the local copy taken will be out of date, but that's all. It won't cause a NullReferenceException.
And yes, there's certainly a race condition - but there always will be. Suppose we just change the code to:
TheEvent(this, EventArgs.Empty);
Now suppose that the invocation list for that delegate has 1000 entries. It's perfectly possible that the action at the start of the list will have executed before another thread unsubscribes a handler near the end of the list. However, that handler will still be executed because it'll be a new list. (Delegates are immutable.) As far as I can see this is unavoidable.
Using an empty delegate certainly avoids the nullity check, but doesn't fix the race condition. It also doesn't guarantee that you always "see" the latest value of the variable.
I see a lot of people going toward the extension method of doing this ...
public static class Extensions
{
public static void Raise<T>(this EventHandler<T> handler,
object sender, T args) where T : EventArgs
{
if (handler != null) handler(sender, args);
}
}
That gives you nicer syntax to raise the event ...
MyEvent.Raise( this, new MyEventArgs() );
And also does away with the local copy since it is captured at method call time.
"Why is explicit-null-check the 'standard pattern'?"
I suspect the reason for this might be that the null-check is more performant.
If you always subscribe an empty delegate to your events when they are created, there will be some overheads:
Cost of constructing the empty delegate.
Cost of constructing a delegate chain to contain it.
Cost of invoking the pointless delegate every single time the event is raised.
(Note that UI controls often have a large number of events, most of which are never subscribed to. Having to create a dummy subscriber to each event and then invoke it would likely be a significant performance hit.)
I did some cursory performance testing to see the impact of the subscribe-empty-delegate approach, and here are my results:
Executing 50000000 iterations . . .
OnNonThreadSafeEvent took: 432ms
OnClassicNullCheckedEvent took: 490ms
OnPreInitializedEvent took: 614ms <--
Subscribing an empty delegate to each event . . .
Executing 50000000 iterations . . .
OnNonThreadSafeEvent took: 674ms
OnClassicNullCheckedEvent took: 674ms
OnPreInitializedEvent took: 2041ms <--
Subscribing another empty delegate to each event . . .
Executing 50000000 iterations . . .
OnNonThreadSafeEvent took: 2011ms
OnClassicNullCheckedEvent took: 2061ms
OnPreInitializedEvent took: 2246ms <--
Done
Note that for the case of zero or one subscribers (common for UI controls, where events are plentiful), the event pre-initialised with an empty delegate is notably slower (over 50 million iterations...)
For more information and source code, visit this blog post on .NET Event invocation thread safety that I published just the day before this question was asked (!)
(My test set-up may be flawed so feel free to download the source code and inspect it yourself. Any feedback is much appreciated.)
I truly enjoyed this read - not! Even though I need it to work with the C# feature called events!
Why not fix this in the compiler? I know there are MS people who read these posts, so please don't flame this!
1 - the Null issue) Why not make events be .Empty instead of null in the first place? How many lines of code would be saved for null check or having to stick a = delegate {} onto the declaration? Let the compiler handle the Empty case, IE do nothing! If it all matters to the creator of the event, they can check for .Empty and do whatever they care with it! Otherwise all the null checks / delegate adds are hacks around the problem!
Honestly I'm tired of having to do this with every event - aka boilerplate code!
public event Action<thisClass, string> Some;
protected virtual void DoSomeEvent(string someValue)
{
var e = Some; // avoid race condition here!
if(null != e) // avoid null condition here!
e(this, someValue);
}
2 - the race condition issue) I read Eric's blog post, I agree that the H (handler) should handle when it dereferences itself, but cannot the event be made immutable/thread safe? IE, set a lock flag on its creation, so that whenever it is called, it locks all subscribing and un-subscribing to it while its executing?
Conclusion,
Are not modern day languages supposed to solve problems like these for us?
With C# 6 and above, code could be simplified using new ?. operator as in:
TheEvent?.Invoke(this, EventArgs.Empty);
Here is the MSDN documentation.
According to Jeffrey Richter in the book CLR via C#, the correct method is:
// Copy a reference to the delegate field now into a temporary field for thread safety
EventHandler<EventArgs> temp =
Interlocked.CompareExchange(ref NewMail, null, null);
// If any methods registered interest with our event, notify them
if (temp != null) temp(this, e);
Because it forces a reference copy.
For more information, see his Event section in the book.
I've been using this design pattern to ensure that event handlers aren't executed after they're unsubscribed. It's working pretty well so far, although I haven't tried any performance profiling.
private readonly object eventMutex = new object();
private event EventHandler _onEvent = null;
public event EventHandler OnEvent
{
add
{
lock(eventMutex)
{
_onEvent += value;
}
}
remove
{
lock(eventMutex)
{
_onEvent -= value;
}
}
}
private void HandleEvent(EventArgs args)
{
lock(eventMutex)
{
if (_onEvent != null)
_onEvent(args);
}
}
I'm mostly working with Mono for Android these days, and Android doesn't seem to like it when you try to update a View after its Activity has been sent to the background.
This practice is not about enforcing a certain order of operations. It's actually about avoiding a null reference exception.
The reasoning behind people caring about the null reference exception and not the race condition would require some deep psychological research. I think it has something to do with the fact that fixing the null reference problem is much easier. Once that is fixed, they hang a big "Mission Accomplished" banner on their code and unzip their flight suit.
Note: fixing the race condition probably involves using a synchronous flag track whether the handler should run
So I'm a little late to the party here. :)
As for the use of null rather than the null object pattern to represent events with no subscribers, consider this scenario. You need to invoke an event, but constructing the object (EventArgs) is non-trivial, and in the common case your event has no subscribers. It would be beneficial to you if you could optimize your code to check to see if you had any subscribers at all before you committed processing effort to constructing the arguments and invoking the event.
With this in mind, a solution is to say "well, zero subscribers is represented by null." Then simply perform the null check before performing your expensive operation. I suppose another way of doing this would have been to have a Count property on the Delegate type, so you'd only perform the expensive operation if myDelegate.Count > 0. Using a Count property is a somewhat nice pattern that solves the original problem of allowing optimization, and it also has the nice property of being able to be invoked without causing a NullReferenceException.
Keep in mind, though, that since delegates are reference types, they are allowed to be null. Perhaps there was simply no good way of hiding this fact under the covers and supporting only the null object pattern for events, so the alternative may have been forcing developers to check both for null and for zero subscribers. That would be even uglier than the current situation.
Note: This is pure speculation. I'm not involved with the .NET languages or CLR.
for single threaded applicaitons, you are correc this is not an issue.
However, if you are making a component that exposes events, there is no guarantee that a consumer of your component is not going to go multithreading, in which case you need to prepare for the worst.
Using the empty delegate does solve the problem, but also causes a performance hit on every call to the event, and could possibly have GC implications.
You are right that the consumer trie dto unsubscribe in order for this to happen, but if they made it past the temp copy, then consider the message already in transit.
If you don't use the temporary variable, and don't use the empty delegate, and someone unsubscribes, you get a null reference exception, which is fatal, so I think the cost is worth it.
I've never really considered this to be much of an issue because I generally only protect against this sort of potential threading badness in static methods (etc) on my reusable components, and I don't make static events.
Am I doing it wrong?
Wire all your events at construction and leave them alone. The design of the Delegate class cannot possibly handle any other usage correctly, as I will explain in the final paragraph of this post.
First of all, there's no point in trying to intercept an event notification when your event handlers must already make a synchronized decision about whether/how to respond to the notification.
Anything that may be notified, should be notified. If your event handlers are properly handling the notifications (i.e. they have access to an authoritative application state and respond only when appropriate), then it will be fine to notify them at any time and trust they will respond properly.
The only time a handler shouldn't be notified that an event has occurred, is if the event in fact hasn't occurred! So if you don't want a handler to be notified, stop generating the events (i.e. disable the control or whatever is responsible for detecting and bringing the event into existence in the first place).
Honestly, I think the Delegate class is unsalvageable. The merger/transition to a MulticastDelegate was a huge mistake, because it effectively changed the (useful) definition of an event from something that happens at a single instant in time, to something that happens over a timespan. Such a change requires a synchronization mechanism that can logically collapse it back into a single instant, but the MulticastDelegate lacks any such mechanism. Synchronization should encompass the entire timespan or instant the event takes place, so that once an application makes the synchronized decision to begin handling an event, it finishes handling it completely (transactionally). With the black box that is the MulticastDelegate/Delegate hybrid class, this is near impossible, so adhere to using a single-subscriber and/or implement your own kind of MulticastDelegate that has a synchronization handle that can be taken out while the handler chain is being used/modified. I'm recommending this, because the alternative would be to implement synchronization/transactional-integrity redundantly in all your handlers, which would be ridiculously/unnecessarily complex.
Please take a look here: http://www.danielfortunov.com/software/%24daniel_fortunovs_adventures_in_software_development/2009/04/23/net_event_invocation_thread_safety
This is the correct solution and should always be used instead of all other workarounds.
“You can ensure that the internal invocation list always has at least one member by initializing it with a do-nothing anonymous method. Because no external party can have a reference to the anonymous method, no external party can remove the method, so the delegate will never be null”
— Programming .NET Components, 2nd Edition, by Juval Löwy
public static event EventHandler<EventArgs> PreInitializedEvent = delegate { };
public static void OnPreInitializedEvent(EventArgs e)
{
// No check required - event will never be null because
// we have subscribed an empty anonymous delegate which
// can never be unsubscribed. (But causes some overhead.)
PreInitializedEvent(null, e);
}
I don't believe the question is constrained to the c# "event" type. Removing that restriction, why not re-invent the wheel a bit and do something along these lines?
Raise event thread safely - best practice
Ability to sub/unsubscribe from any thread while within a raise (race
condition removed)
Operator overloads for += and -= at the class level.
Generic caller-defined delegate
Thanks for a useful discussion. I was working on this problem recently and made the following class which is a bit slower, but allows to avoid callings to disposed objects.
The main point here is that invocation list can be modified even event is raised.
/// <summary>
/// Thread safe event invoker
/// </summary>
public sealed class ThreadSafeEventInvoker
{
/// <summary>
/// Dictionary of delegates
/// </summary>
readonly ConcurrentDictionary<Delegate, DelegateHolder> delegates = new ConcurrentDictionary<Delegate, DelegateHolder>();
/// <summary>
/// List of delegates to be called, we need it because it is relatevely easy to implement a loop with list
/// modification inside of it
/// </summary>
readonly LinkedList<DelegateHolder> delegatesList = new LinkedList<DelegateHolder>();
/// <summary>
/// locker for delegates list
/// </summary>
private readonly ReaderWriterLockSlim listLocker = new ReaderWriterLockSlim();
/// <summary>
/// Add delegate to list
/// </summary>
/// <param name="value"></param>
public void Add(Delegate value)
{
var holder = new DelegateHolder(value);
if (!delegates.TryAdd(value, holder)) return;
listLocker.EnterWriteLock();
delegatesList.AddLast(holder);
listLocker.ExitWriteLock();
}
/// <summary>
/// Remove delegate from list
/// </summary>
/// <param name="value"></param>
public void Remove(Delegate value)
{
DelegateHolder holder;
if (!delegates.TryRemove(value, out holder)) return;
Monitor.Enter(holder);
holder.IsDeleted = true;
Monitor.Exit(holder);
}
/// <summary>
/// Raise an event
/// </summary>
/// <param name="args"></param>
public void Raise(params object[] args)
{
DelegateHolder holder = null;
try
{
// get root element
listLocker.EnterReadLock();
var cursor = delegatesList.First;
listLocker.ExitReadLock();
while (cursor != null)
{
// get its value and a next node
listLocker.EnterReadLock();
holder = cursor.Value;
var next = cursor.Next;
listLocker.ExitReadLock();
// lock holder and invoke if it is not removed
Monitor.Enter(holder);
if (!holder.IsDeleted)
holder.Action.DynamicInvoke(args);
else if (!holder.IsDeletedFromList)
{
listLocker.EnterWriteLock();
delegatesList.Remove(cursor);
holder.IsDeletedFromList = true;
listLocker.ExitWriteLock();
}
Monitor.Exit(holder);
cursor = next;
}
}
catch
{
// clean up
if (listLocker.IsReadLockHeld)
listLocker.ExitReadLock();
if (listLocker.IsWriteLockHeld)
listLocker.ExitWriteLock();
if (holder != null && Monitor.IsEntered(holder))
Monitor.Exit(holder);
throw;
}
}
/// <summary>
/// helper class
/// </summary>
class DelegateHolder
{
/// <summary>
/// delegate to call
/// </summary>
public Delegate Action { get; private set; }
/// <summary>
/// flag shows if this delegate removed from list of calls
/// </summary>
public bool IsDeleted { get; set; }
/// <summary>
/// flag shows if this instance was removed from all lists
/// </summary>
public bool IsDeletedFromList { get; set; }
/// <summary>
/// Constuctor
/// </summary>
/// <param name="d"></param>
public DelegateHolder(Delegate d)
{
Action = d;
}
}
}
And the usage is:
private readonly ThreadSafeEventInvoker someEventWrapper = new ThreadSafeEventInvoker();
public event Action SomeEvent
{
add { someEventWrapper.Add(value); }
remove { someEventWrapper.Remove(value); }
}
public void RaiseSomeEvent()
{
someEventWrapper.Raise();
}
Test
I tested it in the following manner. I have a thread which creates and destroys objects like this:
var objects = Enumerable.Range(0, 1000).Select(x => new Bar(foo)).ToList();
Thread.Sleep(10);
objects.ForEach(x => x.Dispose());
In a Bar (a listener object) constructor I subscribe to SomeEvent (which is implemented as shown above) and unsubscribe in Dispose:
public Bar(Foo foo)
{
this.foo = foo;
foo.SomeEvent += Handler;
}
public void Handler()
{
if (disposed)
Console.WriteLine("Handler is called after object was disposed!");
}
public void Dispose()
{
foo.SomeEvent -= Handler;
disposed = true;
}
Also I have couple of threads which raise event in a loop.
All these actions are performed simultaneously: many listeners are created and destroyed and event is being fired at the same time.
If there were a race conditions I should see a message in a console, but it is empty. But if I use clr events as usual I see it full of warning messages. So, I can conclude that it is possible to implement a thread safe events in c#.
What do you think?
Related
Standard event handler (with operator +=) is one of the memory leakage cause (if it is not unregistered/disposed (with -= operator)).
And Microsoft solved it with WeakEventManager and its inheritance like: PropertyChangedEventManager, CollectionChangedEventManager, CurrentChangedEventManager, ErrorsChangedEventManager and so on.
The simple example code with memory leakage is:
public class EventCaller
{
public static event EventHandler MyEvent;
public static void Call()
{
var handler = MyEvent;
if (handler != null)
{
handler(null, EventArgs.Empty);
Debug.WriteLine("=============");
}
}
}
public class A
{
string myText;
public A(string text)
{
myText = text;
EventCaller.MyEvent += OnCall;
// Use code below and comment out code above to avoid memory leakage.
// System.Windows.WeakEventManager<EventCaller, EventArgs>.AddHandler(null, "MyEvent", OnCall);
}
void OnCall(object sender, EventArgs e)
{
Debug.WriteLine(myText);
}
~A()
{
Debug.WriteLine(myText + " destructor");
}
}
void Main()
{
var a = new A("A");
var b = new A("B");
EventCaller.Call();
a = null;
GC.Collect();
EventCaller.Call();
}
The output is:
A
B
+++++++
A
B
+++++++
We can see that the destructor will not be called.
But if we change (by commenting the unused code) from:
EventCaller.MyEvent += OnCall;
to
System.Windows.WeakEventManager<EventCaller, EventArgs>.AddHandler(null, "MyEvent", OnCall);
And the output is:
A
B
+++++++
B
+++++++
A destructor
B destructor
After A is nulled then its event handler will not be called anymore.
A and B will be disposed after not be used anymore without -= operator.
Can I safely replace all += operator with System.Windows.WeakEventManager to avoid memory leakage due to probably missing event unregistration and saving code by should not implement IDisposable?
If it is not really safe, what should I consider or notice?
Can I safely replace all += operator with System.Windows.WeakEventManager to avoid memory leakage due to probably missing event unregistration and saving code by should not implement IDisposable?
Can you? Probably. Should you? Probably not. If you do have a strong reference to an event handler you should prefer unsubscribe from it if the publisher of the event lives longer than the subscriber of the event rather than replacing the strong reference with a weak event. There are side effects of using weak events. One of them is performance. Another is the semantic difference. You may want to refer to the following question and answers about why the implementation of events in the .NET Framework does not use the weak event pattern by default:
Why is the implementation of events in C# not using a weak event pattern by default?
There are certainly certain scenarios where you should use the weak event pattern. One such scenario is the data binding in WPF where a source object is completely independent of the listener object. But this doesn't mean that you should always use the weak event pattern. And it also doesn't mean that you should stop caring about disposing subscriptions in your applications.
1) I would not take code saving as an argument to use the WeakEventManager instead of implementing IDisposable.
2) In case of the Weak event pattern, event handling will continue until the garbage collecor collects the listener. Unreferencing the listener does not stop event handling immediately as explicit unregistering of a strong referenced event handler in the Dispose pattern does.
3) See the Microsoft documentation concerning Weak Event Patterns
The weak event pattern can be used whenever a listener needs to register for an event, but the listener does not explicitly know when to unregister. The weak event pattern can also be used whenever the object lifetime of the source exceeds the useful object lifetime of the listener. (In this case, useful is determined by you.)
If you explicitly know when to unregister the listener, I would prefer the standard events and implement the Dispose pattern. From the event handlers point of view, explicit unregistration has the advantage that the event handling immediately stops while the weak event pattern continues to handle the events (which also could be CPU and memory consuming) until the garbage collector collects the listener.
A specific case where you can't "blindly" substitute a weak event for a normal one was noted in a post by Thomas Levesque:
If you're subscribing to the event with an anonymous method (e.g. a
lambda expression), make sure to keep a reference to the handler,
otherwise it will be collected too soon.
So you can change it to weak as long as you keep a reference to the anonymous handler method / delegate in addition.
It is obvious that firing events inside of a lock (i.e. critical section) is prone to deadlocks due to the possibility that the event handler may block on some asynchronous operation that also needs to acquire the same lock. Now, design-wise there are two possible solutions that come to my mind:
If it is needed to fire an event inside a lock, then always fire the event asynchronously. This can be performed by using ThreadPool, for example, if the firing order of the events does not matter. If the order of the events must be preserved, then a single event firing thread can be used to fire the events in order, but asynchronously.
The class/library that fires the events does not need to take any necessary precautions to prevent the deadlock and just fire the event inside the lock. In this case it is the event handler's responsibility to process the event asynchronously if it performs locking (or any other blocking operation) inside the event handler. If the event handler does not conform to this rule, then it should suffer the consequences in case a deadlock occurs.
I honestly think that the second option is better in terms of separation of concerns principle as the event-firing code should not guess what the event handler may or may not do.
However, practically, I am inclined to take the first route since the second option seems to converge to the point that every event handler must now run all event-handling code asynchronously, since most of the time it is not clear whether some series of calls performs a blocking operation or not. For complex event-handlers, tracing all possible paths (and, moreover, keeping track of it as the code evolves) is definitely not an easy task. Therefore, solving the problem in one place (where the event is fired) seems to be preferable.
I am interested in seeing if there are other alternative solutions that I may have overlooked and what possible advantages/disadvantages and pitfalls can be attributed to each possible solution.
Is there a best practice for this kind of situation?
There is a third option: Delay raising the event until the lock is released. Normally, locks are taken for a short time. It is usually possible to delay raising the event till after lock (but on the same thread).
The BCL almost never calls user code under a lock. This is an explicit design principle of theirs. For example ConcurrentDictionary.AddOrUpdate does not call the factory while under a lock. This counter-intuitive behavior causes many Stack Overflow questions because it can lead to multiple factory invocations for the same key.
I honestly think that the second option is better in terms of separation of concerns principle as the event-firing code should not guess what the event handler may or may not do.
I don't think the first option violates separation of concerns. Extract an AsyncEventNotifier class and have your event-generating object delegate to it, something like (obviously not complete):
class AsyncEventNotifier
{
private List<EventListener> _listeners;
public void AddEventListener(EventListener listener) { _listeners.add(listener); }
public void NotifyListeners(EventArgs args)
{
// spawn a new thread to call the listener methods
}
....
}
class EventGeneratingClass
{
private AsyncEventHandler _asyncEventHandler;
public void AddEventListener(EventListener listener) { _asyncEventHandler.AddEventListener(listener); }
private void FireSomeEvent()
{
var eventArgs = new EventArgs();
...
_asyncEventhandler.NotifyListeners(eventArgs);
}
}
Now your original class isn't responsible for anything it wasn't responsible for before. It knows how to add listeners to itself and it knows how to tell its listeners that an event has occurred. The new class knows the implementation details of "tell its listeners that an event has occurred". Listener order is also preserved if it's important. It probably shouldn't be, though. If listenerB can't handle an event until listenerA has already handled it then listenerB is probably more interested in an event generated by listenerA than by the object it was listening to. Either that or you should have another class whose responsibility is to know the order that an event needs to be processed in.
I have a situation in my project where i have connect to multiple server and listen for events. Whenever a event received from the server, Handler should add the event to the common queue for processing. All connections should add received events to the queue.
foreach(var item in collection)
{
Connection c = new connection(item);
c.start();
c.EventReceived+=new EventHandler(myHandler);
list.add(c);
}
protected void myHandler(eventArgs)
{
//add it to the concurrent queue
}
Here i doubt that whether it can be able to handle those events without any threading issues. Please let me know if you have any patterns or built in APIs to handle this safely.
Thread-safety always needs a context - a from what.
If you mean the +=
For the +=, that depends on how the event is implemented. If it is implemented as a field-like event, i.e.
public event SomeEventType EventReceived;
then yes: it is thread-safe. The specification requires that the accessors for field-like events are thread-safe, although the implementation can vary (for example, the MS compiler used to use lock(this) or lock(typeof(DeclaringType)), however it now uses Interlocked instead).
If the event is implemented manually, i.e.
public event SomeEventType EventReceived {
add { ... }
remove { ... }
}
Then the thread-safety is defined entirely by the add/remove implementations.
If you mean the invoke
Then that is thread-safe since delegates are immutable, but note that it all happens on the single thread that invokes the thread. However, a common mistake is to introduce a race condition in a null test:
if(EventReceived != null) EventReceived(this, someArgs);
The above is not thread-safe, since technically the value of EventReceived can change after the test. To ensure this does not error, it should be:
var handler = EventReceived;
if(handler != null) handler(this, someArgs);
If you mean the handlers
Then the thread-safety is defined entirely by the individual handlers. For example, in UI applications it is the handlers that must check for, and switch to, the UI thread.
Quoting from C# spec
When compiling a field-like event, the compiler automatically creates
storage to hold the delegate, and creates accessors for the event that
add or remove event handlers to the delegate field. In order to be thread-safe,
the addition or removal operations are done while holding the lock (§8.12)
on the containing object for an instance event, or the type object (§7.6.10.6)
for a static event.
Bottom line is if the EventReceived is field like event(non custom implementation) then its thread safe!
Update
Current implementation uses Interlocked for thread safety
Most code I have seen uses the following way to declare and invoke event firing:
public class MyExample
{
public event Action MyEvent; // could be an event EventHandler<EventArgs>, too
private void OnMyEvent()
{
var handler = this.MyEvent; // copy before access (to aviod race cond.)
if (handler != null)
{
handler();
}
}
public void DoSomeThingsAndFireEvent()
{
// ... doing some things here
OnMyEvent();
}
}
Even ReSharper generates an invoking method the way mentioned above.
Why not just do it this way:
public class MyExample
{
public event Action MyEvent = delegate {}; // init here, so it's never null
public void DoSomeThingsAndFireEvent()
{
// ... doing some things here
OnMyEvent(); // save to call directly because this can't be null
}
}
Can anyone explain a reason why not to do this? (pro vs. cons)
The pros and cons are:
null checks are extremely cheap; we're talking billionths of a second. Allocating a delegate and then garbage collecting it unsuccessfully for the rest of the lifetime of the object could take maybe upwards of a few millionths of a second. Plus, you're consuming dozens of bytes more memory. Plus, every time the event fires, you get an unnecessary call to a method that does nothing, consuming even more microseconds. If you're the sort of person who cares about millionths of a second and dozens of bytes then that might be a meaningful difference; for the vast majority of cases it will not.
You have to remember to always create the empty delegate. Is that really any easier than remembering to check for null?
Neither pattern actually makes the event threadsafe. It is still entirely possible with both patterns for an event handler to be fired on one thread while being removed on another thread, and that means that they race. If your handler removal code destroys state that the handler needs, then it is possible that one thread is destroying that state while another thread is running the handler. Do not think that merely checking for null or assigning an empty handler magically eliminates race conditions. It only eliminates the race condition that results in dereferencing null.
It is a style thing for sure; however, I think most developers go for safety over style when it comes to null checks. There is nothing in this world that can guarantee that a bug will not creep into the system and that null check will continue to be unnecessary.
It can still be null. Consider:
var x = new MyExample();
x.MyEvent += SomeHandler;
// ... later, when the above code is disposed of
x.MyEvent -= SomeHandler;
EDIT: actually, I take it back. Having tested this, if you've used an anonymous delegate to set the handler, it doesn't look like you can clear it, so you can save the null check.
I'm not sure whether this is reliable behaviour though, or just an artifact of the language implementation...
The best tradeoff I've seen for simplifying event firing is the addition of an extension method. See Raising C# events with an extension method - is it bad?.
Problem background
An event can have multiple subscribers (i.e. multiple handlers may be called when an event is raised). Since any one of the handlers could throw an error, and that would prevent the rest of them from being called, I want to ignore any errors thrown from each individual handler. In other words, I do not want an error in one handler to disrupt the execution of other handlers in the invocation list, since neither those other handlers nor the event publisher has any control over what any particular event handler's code does.
This can be accomplished easily with code like this:
public event EventHandler MyEvent;
public void RaiseEventSafely( object sender, EventArgs e )
{
foreach(EventHandlerType handler in MyEvent.GetInvocationList())
try {handler( sender, e );}catch{}
}
A generic, thread-safe, error-free solution
Of course, I don't want to write all this generic code over and over every time I call an event, so I wanted to encapsulate it in a generic class. Furthermore, I'd actually need additional code to ensure thread-safety so that MyEvent's invocation list does not change while the list of methods is being executed.
I decided to implement this as a generic class where the generic type is constrained by the "where" clause to be a Delegate. I really wanted the constraint to be "delegate" or "event", but those are not valid, so using Delegate as a base class constraint is the best I can do. I then create a lock object and lock it in a public event's add and remove methods, which alter a private delegate variable called "event_handlers".
public class SafeEventHandler<EventType> where EventType:Delegate
{
private object collection_lock = new object();
private EventType event_handlers;
public SafeEventHandler(){}
public event EventType Handlers
{
add {lock(collection_lock){event_handlers += value;}}
remove {lock(collection_lock){event_handlers -= value;}}
}
public void RaiseEventSafely( EventType event_delegate, object[] args )
{
lock (collection_lock)
foreach (Delegate handler in event_delegate.GetInvocationList())
try {handler.DynamicInvoke( args );}catch{}
}
}
Compiler issue with += operator, but two easy workarounds
One problem ran into is that the line "event_handlers += value;" results in the compiler error "Operator '+=' cannot be applied to types 'EventType' and 'EventType'". Even though EventType is constrained to be a Delegate type, it will not allow the += operator on it.
As a workaround, I just added the event keyword to "event_handlers", so the definition looks like this "private event EventType event_handlers;", and that compiles fine. But I also figured that since the "event" keyword can generate code to handle this, that I should be able to as well, so I eventually changed it to this to avoid the compiler's inability to recognize that '+=' SHOULD apply to a generic type constrained to be a Delegate. The private variable "event_handlers" is now typed as Delegate instead of the generic EventType, and the add/remove methods follow this pattern event_handlers = MulticastDelegate.Combine( event_handlers, value );
The final code looks like this:
public class SafeEventHandler<EventType> where EventType:Delegate
{
private object collection_lock = new object();
private Delegate event_handlers;
public SafeEventHandler(){}
public event EventType Handlers
{
add {lock(collection_lock){event_handlers = Delegate.Combine( event_handlers, value );}}
remove {lock(collection_lock){event_handlers = Delegate.Remove( event_handlers, value );}}
}
public void RaiseEventSafely( EventType event_delegate, object[] args )
{
lock (collection_lock)
foreach (Delegate handler in event_delegate.GetInvocationList())
try {handler.DynamicInvoke( args );}catch{}
}
}
The Question
My question is... does this appear to do the job well? Is there a better way or is this basically the way it must be done? I think I've exhausted all the options. Using a lock in the add/remove methods of a public event (backed by a private delegate) and also using the same lock while executing the invocation list is the only way I can see to make the invocation list thread-safe, while also ensuring errors thrown by handlers don't interfere with the invocation of other handlers.
Since any one of the handlers could throw an error, and that would prevent the rest of them from being called,
You say that like it is a bad thing. That is a very good thing. When an unhandled, unexpected exception is thrown that means that the entire process is now in an unknown, unpredictable, possibly dangerously unstable state.
Running more code at this point is likely to make things worse, not better. The safest thing to do when this happens is to detect the situation and cause a failfast that takes down the entire process without running any more code. You don't know what awful thing running more code is going to do at this point.
I want to ignore any errors thrown from each individual handler.
This is a super dangerous idea. Those exceptions are telling you that something awful is happening, and you're ignoring them.
In other words, I do not want an error in one handler to disrupt the execution of other handlers in the invocation list, since neither those other handlers nor the event publisher has any control over what any particular event handler's code does.
Whose in charge here? Someone is adding those event handlers to this event. That is the code that is responsible for ensuring that the event handlers do the right thing should there be an exceptional situation.
I then create a lock object and lock it in a public event's add and remove methods, which alter a private delegate variable called "event_handlers".
Sure, that's fine. I question the necessity of the feature -- I very rarely have a situation where multiple threads are adding event handlers to an event -- but I'll take your word for it that you are in this situation.
But in that scenario this code is very, very, very dangerous:
lock (collection_lock)
foreach (Delegate handler in event_delegate.GetInvocationList())
try {handler.DynamicInvoke( args );}catch{}
Let's think about what goes wrong there.
Thread Alpha enters the collection lock.
Suppose there is another resource, foo, which is also controlled by a different lock. Thread Beta enters the foo lock in order to obtain some data that it needs.
Thread Beta then takes that data and attempts to enter the collection lock, because it wants to use the contents of foo in an event handler.
Thread Beta is now waiting on thread Alpha. Thread Alpha now calls a delegate, which decides that it wants to access foo. So it waits on thread Beta, and now we have a deadlock.
But can't we avoid this by ordering the locks? No, because the very premise of your scenario is that you don't know what the event handlers are doing! If you already know that the event handlers are well-behaved with respect to their lock ordering then you can presumably also know that they are well-behaved with respect to not throwing exceptions, and the whole problem vanishes.
OK, so let's suppose that you do this instead:
Delegate copy;
lock (collection_lock)
copy = event_delegate;
foreach (Delegate handler in copy.GetInvocationList())
try {handler.DynamicInvoke( args );}catch{}
Delegates are immutable and copied atomically by reference, so you now know that you're going to be invoking the contents of event_delegate but not holding the lock during the invocation. Does that help?
Not really. You've traded one problem for another one:
Thread Alpha takes the lock and makes a copy of the delegate list, and leaves the lock.
Thread Beta takes the lock, removes event handler X from the list, and destroys state necessary to prevent X from deadlocking.
Thread Alpha takes over again and starts up X from the copy. Because Beta just destroyed state necessary for the correct execution of X, X deadlocks. And once more, you are deadlocked.
Event handlers are required to not do that; they are required to be robust in the face of their suddenly becoming "stale". It sounds like you are in a scenario where you cannot trust your event handlers to be well-written. That's a horrid situation to be in; you then cannot trust any code to be reliable in the process. You seem to think that there is some level of isolation you can impose on an event handler by catching all its errors and muddling through, but there is not. Event handlers are just code, and they can affect arbitrary global state in the program like any other code.
In short, your solution is generic, but it is not threadsafe and it is not error-free. Rather, it exacerbates threading problems like deadlocks and it turns off safety systems.
You simply cannot abdicate responsibility for ensuring that event handlers are correct, so don't try. Write your event handlers so that they are correct -- so that they order locks correctly and never throw unhandled exceptions.
If they are not correct and end up throwing exceptions then take down the process immediately. Don't keep muddling through trying to run code that is now living in an unstable process.
Based on your comments on other answers it looks like you think that you should be able to take candy from strangers with no ill effects. You cannot, not without a whole lot more isolation. You can't just sign up random code willy-nilly to events in your process and hope for the best. If you have stuff that is unreliable because you're running third party code in your application, you need a managed add-in framework of some sort to provide isolation. Try looking up MEF or MAF.
The lock inside RaiseEventSafely is both unnecessary and dangerous.
It is unnecessary because delegates are immutable. Once you read it, the invokation list you obtained will not change. It doesn't matter if the changes happen while event code runs, or if the changes need to wait until after.
It is dangerous because you're calling external code while holding a lock. This can easily lead to lock order violations and thus deadlocks. Consider an eventhandler that spawns a new thread that tries to modify the event. Boom, deadlock.
The you have an empty catch for exception. That's rarely a good idea, since it silently swallows the exception. At minimum you should log the exception.
Your generic parameter doesn't start with a T. That's a bit confusing IMO.
where EventType:Delegate I don't think this compiles. Delegate is not a valid generic constraint. For some reason the C# specification forbids certain types as a generic constraint, and one of them is Delegate. (no idea why)
Have you looked into the PRISM EventAggregator or MVVMLight Messenger classes? Both of these classes fulfill all your requirements. MVVMLight's Messenger class uses WeakReferences to prevent memory leaks.
Aside from it being a bad idea to swallow exceptions, I suggest you consider not locking while invoking the list of delegates.
You'll need to put a remark in your class's documentation that delegates can be called after having been removed from the event.
The reason I'd do this is because otherwise you risk performance consequences and possibly deadlocks. You're holding a lock while calling into someone else's code. Let's call your internal lock Lock 'A'. If one of the handlers attempts to acquire a private lock 'B', and on a separate thread someone tries to register a handler while holding lock 'B', then one thread holds lock 'A' while trying to acquire 'B' and a different thread holds lock 'B' while trying to acquire lock 'A'. Deadlock.
Third-party libraries like yours are often written with no thread safety to avoid these kinds of issues, and it is up to the clients to protect methods that access internal variables. I think it is reasonable for an event class to provide thread safety, but I think the risk of a 'late' callback is better than a poorly-defined lock hierarchy prone to deadlocking.
Last nit-pick, do you think SafeEventHandler really describes what this class does? It looks like an event registrar and dispatcher to me.
It is a bad practice to swallow exceptions entirely. If you have a use case where you would like a publisher to recover gracefully from an error raised by a subscriber then this calls for the use of an event aggregator.
Moreover, I'm not sure I follow the code in SafeEventHandler.RaiseEventSafely. Why is there an event delegate as a parameter? It seems to have no relationship with the event_handlers field. As far as thread-safety, after the call to GetInvocationList, it does not matter if the original collection of delegates is modified because the array returned won't change.
If you must, I would suggest doing the following instead:
class MyClass
{
event EventHandler myEvent;
public event EventHandler MyEvent
{
add { this.myEvent += value.SwallowException(); }
remove { this.myEvent -= value.SwallowException(); }
}
protected void OnMyEvent(EventArgs args)
{
var e = this.myEvent;
if (e != null)
e(this, args);
}
}
public static class EventHandlerHelper
{
public static EventHandler SwallowException(this EventHandler handler)
{
return (s, args) =>
{
try
{
handler(s, args);
}
catch { }
};
}
}
Juval Löwy provides an implementation of this in his book "Programming .NET components".
http://books.google.com/books?id=m7E4la3JAVcC&lpg=PA129&pg=PA143#v=onepage&q&f=false
I considered everything everyone said, and arrived at the following code for now:
public class SafeEvent<EventDelegateType> where EventDelegateType:class
{
private object collection_lock = new object();
private Delegate event_handlers;
public SafeEvent()
{
if(!typeof(Delegate).IsAssignableFrom( typeof(EventDelegateType) ))
throw new ArgumentException( "Generic parameter must be a delegate type." );
}
public Delegate Handlers
{
get
{
lock (collection_lock)
return (Delegate)event_handlers.Clone();
}
}
public void AddEventHandler( EventDelegateType handler )
{
lock(collection_lock)
event_handlers = Delegate.Combine( event_handlers, handler as Delegate );
}
public void RemoveEventHandler( EventDelegateType handler )
{
lock(collection_lock)
event_handlers = Delegate.Remove( event_handlers, handler as Delegate );
}
public void Raise( object[] args, out List<Exception> errors )
{
lock (collection_lock)
{
errors = null;
foreach (Delegate handler in event_handlers.GetInvocationList())
{
try {handler.DynamicInvoke( args );}
catch (Exception err)
{
if (errors == null)
errors = new List<Exception>();
errors.Add( err );
}
}
}
}
}
This bypasses the compiler's special treatment of the Delegate as an invalid base class. Also, events cannot be typed as Delegate.
Here is how a SafeEvent would be used to create an event in a class:
private SafeEvent<SomeEventHandlerType> a_safe_event = new SafeEvent<SomeEventHandlerType>();
public event SomeEventHandlerType MyEvent
{
add {a_safe_event.AddEventHandler( value );}
remove {a_safe_event.RemoveEventHandler( value );}
}
And here is how the event would be raised and errors handled:
List<Exception> event_handler_errors;
a_safe_event.Raise( new object[] {event_type, disk}, out event_handler_errors );
//Report errors however you want; they should not have occurred; examine logged errors and fix your broken handlers!
To summarize, this component's job is to publish events to a list of subscribers in an atomic manner (i.e. the event will not be re-raised and the invocation list will not be changed while the invocation list is executing). Deadlock is possible but easily avoided by controlling access to the SafeEvent, because a handler would have to spawn a thread that calls one of the public methods of the SafeEvent and then wait on that thread. In any other scenario, other threads would simply block until the lock owning-thread releases the lock. Also, while I do not believe in ignoring errors at all, I also do not believe that this component is in any place to handle subscriber errors intelligently nor make a judgement call about the severity of such errors, so rather than throw them and risk crashing the application, it reports errors to the caller of "Raise", since the caller is likely to be in a better position to handle such errors. With that said, this components provides a kind of stability to events that's lacking in the C# event system.
I think what people are worried about is that letting other subscribers run after an error has occurred means they are running in an unstable context. While that might be true, that means the application is in fact written incorrectly any way you look at it. Crashing is no better a solution than allowing the code to run, because allowing the code to run will allow errors to be reported, and will allow the full effects of the error to be manifest, and this, in turn, will assist engineers to more quickly and thoroughly understand the nature of the error and FIX THEIR CODE FASTER.