Defensive event publishing in .NET – Part I

This article was inspired by Juval Lowy’s Advanced .NET master class (Copyrights © IDesign 2005) and contains code excerpts from Programming .NET Components (1st Edition) By O'Reilly 2003.

 

Summary

Events and delegates in the .NET Framework present an interesting case of apparent simplicity with abundant complexity underneath. Unfortunately, we *have* to take into account the complexity underneath if we are to use events correctly in our applications. What I’m suggesting here is that most developers today are *not* raising events correctly.  Even most of the “advanced” developers out there are not doing all the necessary steps in order to make sure the events are published in a safe manner.

 

 

The case of the innocent coder

 

Take the following code as a starting point:

 

public event EventHandler Clicked;

 

private void FireClickedEvent()

{

   Clicked(this,EventArgs.Empty);

}

 

“This isn’t good code” most of you will say immediately. “You’re not checking to make sure the event is not null. And that’s true. An event with no subscriber is set to null by the runtime. That means that running this code will result in an exception. Consider the following code then:

 

private void FireClickedEvent()

{

   if(Clicked!=null)

      Clicked(this,EventArgs.Empty);

}

 

 

 

Attack of the event subscribers

 

“That’s better”, most of you will say and continue on your merry way as if the code is fine and life is good. But, are they really?  Picture a state in which there are 10 event subscribers in your application. By design, your event is raised to each of them on the same thread.  What happens if the 3rd subscriber receives the event and throws an exception? Yep. You event will stop bubbling to the rest of the subscribers. That means that 7 clients will not receive your event and blow you up in the process. So what do you need to do? You need to manually go into the list of subscribers that your event will publish to and iterate over each one, manually activating the event for each of them and doing all this inside a try-catch block. To get into the subscriber list you go into your event’s “Invocation list”. An event is simply a delegate which is decorated with the “event” keyword. All delegates have an invocation list which exposes the list of subscribers. Here’s how the code looks now:

 

private void FireClickedEvent()

{

    if(Clicked != null)

    {

        Delegate[] list = Clicked.GetInvocationList();

        foreach (Delegate del in list)

        {

            try

            {

                EventHandler handler = (EventHandler)del;

                handler(this, EventArgs.Empty);

            }

            catch { }

        }

    }

}

 

Refactoring: Extract Utility Class

 

Better. But now consider the amount of code you need to write for each event firing code. What’s missing here is a more generic way of throwing the events. Let’s make an EventsHelper class that fires the event for us. To do that we need the ability to invoke any delegate in a generic way, regardless of the parameters that it expects.

Help arrives in the form of Delegate.DynamicInvoke().  Dynamic invocation allows us to send any parameters into a delegate invocation. The upside is that now you can write generic code that looks like this:

 

public class EventsHelper

{

    public static void Fire(Delegate del,params object[] args)

    {

        if (del == null)

        {

            return;

        }

        Delegate[] delegates = del.GetInvocationList();

        foreach (Delegate sink in delegates)

        {

            InvokeDelegate(sink,args);

        }

    }

   

    private static void InvokeDelegate(Delegate sink,object[] args)

    {

        try

        {

            sink.DynamicInvoke(args);

        }

        catch

        {}

    }

}

 

Which means that now we can write code that looks like this in our original class:

 

 private void FireClickedEvent()

 {

     EventsHelper.Fire(Clicked,this,EventArgs.Empty);

 }

 

But there’s a downside as well: invoking the delegate just became a non-type safe activity. That means that the user of the events helper may be able to send in the wrong parameters in code to invoke an event, but the compiler won’t complain about this. We’ll see how we solve this problem in .NET 2.0 when we discuss generics in part II of this article. For now, we have even more important potential issues we need to worry about.

 

Return of the killer event subscribers

 

Consider the earlier scenario of multiple subscribers. Now imagine that no subscriber throws an exception, but instead, now the 3rd subscriber does very lengthy processing. Since all events are sent in a synchronous manner, the 4th subscriber and so on may receive the events in a delay which may render the event meaningless (for example, events that mark the passing of a single second but which take 3 seconds to process).

The way to overcome this is of course to invoke the delegate asynchronously on a thread different than the calling thread. That way we don’t care how long it takes for each event subscriber to process the event, we just keep going through our invocation list without worries, never blocking for any subscriber. To that end we can use the delegate's BeginInvoke() method,

 

 

which automatically will invoke the delegate on a different thread.  The plan: We’re still going to call the “InvokeDelegate” method, only we’re going to use our own delegate to call it from within EventsHelper, and we’re going to call it asynchronously for each of the delegates in the invocation list (changed  lines are highlighted):

 

public class EventsHelper

{

    delegate void AsyncInvokeDelegate(Delegate del, params object[] args);

 

    public static void FireAsync(Delegate del, params object[] args)

    {

        if (del == null)

        {

           return;

        }

        Delegate[] delegates = del.GetInvocationList();

       

        AsyncInvokeDelegate invoker = new AsyncInvokeDelegate(InvokeDelegate);

        foreach (Delegate sink in delegates)

        {

           invoker.BeginInvoke(sink,args,null,null);

  }

    }

 

 

The BeginInvoke method of a delegate will automatically run the target method on a thread from the thread pool. Notice the last two parameters. These are used in cases where we want to be able to get a callback when the target method finishes execution. Since in this scenario we don’t really care (the whole idea of firing events is “fire and forget”) we’ll leave these alone to specific articles on those issues. For now, this will suffice in letting us raise events in an asynchronous way.

Are we done yet?

The answer is, of course, “Hell no!”.

 

 

 

 

The case of the hidden resource leak

 

One of the things we need to watch out for is resource leaks. It’s a little known fact that whenever you invoke a delegate asynchronously, it keeps aside some information about the call, arguments, errors, returned value, signaling event, state and so on, for purposes of callback and other things. Consider what’s going to happen if our application calls the EventsHelper 5 million times a day for a month, without restarting. Can you guess what will happen to the computer’s memory and resources?

Because we don’t really care for all that saved information, we can make the delegate ignore it and not save it, by placing a [OneWay] attribute on the method that the delegate invokes. We can’t trust our event subscribers to do this, can we? Luckily, we already have a method which is a perfect candidate for this attribute – you guessed it – the “InvokeDelegate” method. Because we call it asynchronously using our own internal delegate, we can simply signal that method as [OneWay] and be done with it:

 

[OneWay]

 private static void InvokeDelegate(Delegate sink,object[] args)

 {

     try

     {

       //execute delegate invocation

 

 

 

 

 

Are we done already? Not really, but we’ve sure come a long way. We now have a generic class now that you can use in your applications. You can download the full version of this class from the IDesign website here (along with many other useful code snippets and solutions!)

 

Unfortunately, I’ll have to stop this article mid way; the reason being that some of the stuff that was shown in Juval’s class was excerpted from his new book, “Programming .NET Components, 2nd edition”, that which will only be published in April 2005. Since there are still copyright issues in showing that intellectual property, part II  of this article will have to wait until then. 

Published Sunday, January 09, 2005 12:11 AM by RoyOsherove

Comments

Saturday, January 08, 2005 10:17 AM by TrackBack

# [Article] Defensive event publishing in .NET

Saturday, January 08, 2005 6:35 PM by Ian Griffiths

# re: New: Defensive event publishing in .NET – Part I

Hmm... But in practice, how often does any of this really matter? I rarely have more than one event subscriber...

More importantly, I think in the case of your catch {} the 'cure' here is a lot worse than the disease. The supposed improvement here is that if one of the handlers throws an exception, the rest still get notified. But the downside is that if one of my handlers throws an exception, I never get to find out!

On the whole, if an exception occurs where I wasn't expecting one, I'd rather find out than have the application plough on stoically.

As for the resource leak, you've overstated the problem, and underengineered the solution! All that saved stuff will get picked up by the GC. And the interesting thing is that it gets picked up *exactly* as quickly as it would do if you called EndInvoke like you're meant to. That's an implementation detail of the current version of the CLR though. And as for the [OneWay] workaround, aren't you also depending on an implementation detail of the CLR here? Is there anything in the documentation that gives me reason to suppose the the presence of this attribute will have the slightest difference on the upshot of not calling EndInvoke like the docs tell me to?

[OneWay] is mainly designed for remoting scenarios isn't it? (It happens to have some mild interactions with async delegate invocation because aync delegate invocation happens to share some infrastructure with remoting under the covers. Today.)

If I need to be able to notify multiple subscribers where those subscribers are flakey, then maybe events simply aren't the right mechanism?
Saturday, January 08, 2005 6:45 PM by joe

# re: New: Defensive event publishing in .NET – Part I

Your advice is bad. Sometimes this may be the right way, sometimes it may not. There are many instances when continuing to propogate the event to other listeners when one fails is in fact NOT what you want. As always, this is just another techinque and it should be used where appropriate, not applied blindly across the board.
Saturday, January 08, 2005 6:54 PM by Roy Osherove

# re: New: Defensive event publishing in .NET – Part I

Ian:
- "But the downside is that if one of my handlers throws an exception, I never get to find out! "

We're talking about a publish-subscribe scenario. When your componenet fires an event it should *never in a million years* care what any of the subscribers do with the event. It should't know who they are, how many are there, and what they should and should not be doing, whether they throw the exception, handle it, or don't do anything. Your claim would be correct if we were talking about a standard callback mechanism, which is a different logical model, where you probably want to know that your message got to all the subscribers.


- "All that saved stuff will get picked up by the GC. And the interesting thing is that it gets picked up *exactly* as quickly as it would do if you called EndInvoke like you're meant to"

The GC will never clean up the the resources that are used by the delegate inside out EventsHelper class (the one we use to execute the "InvokeDelegate" method with). That's because it is static and will staty in memory for as long as the AppDomain that holds the static class will.
And you should call EndInvoke when you *care* about the outcome ofr your callback, which is not the case in the event subscriber model. If you're talking about a requirement that says "reliable messaging needed", that's something else. But with events, you should really jsut notify the subscribers and move on as quickly as you can.

- "If I need to be able to notify multiple subscribers where those subscribers are flakey, then maybe events simply aren't the right mechanism? "

If you need reliable messaging, and your component should be coupled with the subscribers, yes, that's not the model for you. This model is right for when you can't know in advance who your subscribers will be, and have no control over them (that is, assume they all throw exceptions or take a long time to process, because you can't prove they won't).
Sunday, January 09, 2005 4:04 AM by Nir

# re: Defensive event publishing in .NET – Part I

if you write a component that runs inside someone else's application and the application does something bad (like throwing an exception or taking too long to respond) you should just let the application crush or stop responding, your user should then debug the application and fix it

if you are the application calling a plugin then it's a totally different story and you should program defensively, but this is not a common use of events

but the really evil thing you have done here is calling events on another thread, the reasons are:
1. writing good multi threading safe code is really hard
2. nobody expects an event to fire on a different thread

this is a trap for programmers that are not familiar with your style, and a really big one

what you just did is force a lot of extra complexity on your user in the name of some in "publish-subscribe
scenario subscribers don't care" ideal

you just made your user's work much more difficult because you wanted a pure textbook publish-subscribe implementation

I work with a component that eat away exceptions and calls events in random threads in my current project, it's the hardest component to work with I have ever used, it forces me to write complex thread synchronization code for what should have been a simple single threaded application (and when that code fails it gives no indication and just continues like nothing happened)

this is not a good programming practice and I hope people don't start writing code like that without a very good reason

if you want to see how bad this is as a general practice just think of a button class that fires it's events like you wrote, now think about a program that changers a label when a button is pressed (a WinForms object can only be accessed from the thread that created it) - just look at all the added code and complexity (and bugs)
Sunday, January 09, 2005 4:24 AM by Roy Osherove

# re: Defensive event publishing in .NET – Part I

Nir:
- "nobody expects an event to fire on a different thread "

Unless they want any kind of asynchronous invocation, you mean. In Winforms applications this happens all the time. You want to make you application responsive while performing lengthy operations so you do the operations using the thread pool or other threading technique. What happens when you call a web service from your winform? Should your user just wait against an application that is stuck for 3 seconds?
In fact, that's the main reason that in .Net 2.0 you have the Background Worker component implementation - to let you implement asynchronous behavior in a GUI thread safe manner.
One of the things that will be shown in the book is how to solve the threading questions. Unfortunately, I can't write about it without overstepping some legalities, so we'll leave it at that for now.

- "this is not a good programming practice and I hope people don't start writing code
like that without a very good reason "

Multi threaded winform apps (and win32 apps) have existed since the beginning of time, basically. Are you saying everyone should just not use asynchronous invocation, ever? Are you saying that when an event fires, it should *always* be susceptible to exceptions, lengthy operations and such from its subscribers? Always?
What about the thousands of applications to which this scenario is perfect?
What you're talking about is a callback and communication mechanism (for plugins and such) where this does not fit.

Sure, threads lead to bugs, but there's a very easy usage scenario here for GUI thread on the form getting the event: "If(InvokeRequired) {Invoke(MyEvent, args);}"
Sunday, January 09, 2005 6:53 AM by Roy Osherove

# re: Defensive event publishing in .NET – Part I

BTW, there's nothing preventing you from firing the event in a sychrounous manner if that's what your component needs. Put a "Fire" and another "AsyncFire" method on the EventsHelper. One calls InvokeDelegate using BeginInvoke, and one calls directly.
Sunday, January 09, 2005 7:36 AM by Ian Griffiths

# re: Defensive event publishing in .NET – Part I

On the subject of swallowing exceptions, Roy wrote:

"We're talking about a publish-subscribe scenario. When your componenet fires an event it should *never in a million years* care what any of the subscribers do with the event. It should't know who they are, how many are there, and what they should and should not be doing, whether they throw the exception, handle it, or don't do anything."

This is the heart of the flaw in your argument. It sure would be nice for our event sources not to know anything about how subscribers work. But in reality that's just not possible. This will take a little explaining, but please bear with me.

Consider the specific case of exception handling - are you saying that Windows Forms takes the wrong approach here? It has an exception handler in its event processing loop. This means that if an event handler allows an exception to propagate back to the event source, there is a centralized mechanism for dealing with this. (So long as event sources don't attempt to swallow the exception. The code you show here would fail to operate correctly in this scenario.)

Note that this particular aspect of the way events are handled in Windows Forms is ENTIRELY compatible with your stricture that an event source shouldn't care what the event handler does - controls in Windows Forms don't need to do anything special to enable this to work - they just let the exception propagate up.

In fact if you follow your own advice - that an event source shouldn't make assumptions about the event handler - then surely you MUST NOT swallow exceptions like you are doing. By swallowing the exception, you are making the assumption that the exception was unimportant - sure you need to know a lot about the code that threw the exception to be able to make that decision!

I think you are assuming a very specific use case for delegates and events here. The truth is that there are many different behaviours that an event source might reasonably implement for exceptions, depending on how you are using events.

But I think that swallowing the exception is pretty much the wrong thing to do in the majority of circumstances. At a bear minimum, it should log some kind of diagnostic trace.


Roy: "Your claim would be correct if we were talking about a standard callback mechanism, which is a different logical model, where you probably want to know that your message got to all the subscribers. "

It's not clear what you think a "standard callback" is. In Win32, the term callback typically refers to a single function callback, so it doesn't even make sense to talk of multiple subscribers.

Again, you seem to have a very specific use of the event/delegate mechanism in mind here: why are you assuming that I probably don't care whether the message got to all the subscribers? Given that the under the covers, events are raised by calling functions through delegates, it's certainly possible for me to know when the handlers have finished. So who are you to declare that nobody is allowed to design a system that takes advantage of this? (Especially when there are examples of systems that do depend on this very feature in the .NET Framework already.)



Ian: "All that saved stuff will get picked up by the GC. And the interesting thing is that it gets picked up *exactly* as quickly as it would do if you called EndInvoke like you're meant to"

Roy: "The GC will never clean up the the resources that are used by the delegate inside out EventsHelper class (the one we use to execute the "InvokeDelegate" method with). That's because it is static and will staty in memory for as long as the AppDomain that holds the static class will. "

Well now you're changing the subject - the fact that certain static data is never collected is entirely unconnected with how you do event notification. Using the [OneWay] attribute will make absolutely no difference to that. And everything else will get collected whether you use [OneWay] or not.

My point was that the use of the [OneWay] attribute doesn't actually contribute anything useful when it comes to reclamation of resources - the resource handling behaviour is unaffected by this attribute.


Roy: "And you should call EndInvoke when you *care* about the outcome ofr your callback, which is not the case in the event subscriber model."

This is unequivocally wrong!

You MUST call EndInvoke whenever you call BeginInvoke, even if you don't care about the results. That is the whole rule. The documentation is clear about this. (At least it is now.)

There was a popular misconception around for a long time that EndInvoke was optional unless you cared about the results. This misconception wasn't helped by the fact that Microsoft forgot to document the fact that EndInvoke isn't optional until some time after .NET v1.0 actually shiped... This allowed the whole 'fire and forget' pattern to become widely established, even though it turns out to be something you should never do. But it's pretty clear now - the "Asynchronous Programming Overview" topic in the help says:

"CAUTION Always call EndInvoke after your asynchronous call completes."

The documentation for OneWayAttribute says nothing about making EndInvoke optional. So there is no reason to suppose that applying [OneWay] will make it clean everything up for you.

And as it happens, in .NET v1.1 today, if you don't use [OneWay] *and* you forget to call EndInvoke, nothing bad happens so long as you didn't ask the call object for a WaitHandle. (And even if you did, then what happens is only slightly bad.) If you don't hold onto the call object (IAsyncResult) the GC will detect that it's unreachable, and that will mean all the resources it allocated are also now unreachable. Finalizers run, objects are collected, the resources are now freed. Obviously it's better to call EndInvoke to ensure early freeing of handles rather than relying on finalizers, but actually, unless you asked for a WaitHandle from the call object, no handles are allocated in practice, so you get away without calling EndInvoke.

That's how it works today. But that's just an implementation detail. Adding [OneWay] makes no difference. Nor does the documentation give us any reason to suppose that it will - the fact that it also happens not to leak today if you use [OneWay] is also just an implementation detail. If you want to be robust for the future, you *must* call EndInvoke. Whether you apply [OneWay] or not.

It is of course *conceivable* that a future version of the CLR might well clean up resources earlier for a [OneWay] method than other methods. But you're now speculating about some fairly unlikely behaviour not implied by the documentation. If you want to be robust for the future it's clear: you have to call EndInvoke.


Roy: "If you're talking about a requirement that says "reliable messaging needed", that's something else. But with events, you should really jsut notify the subscribers and move on as quickly as you can. "

Again, you're defining arbitrary restrictions on the use of the event mechanism. There are many viable uses, and you're just characterising a subset.

In-process, there is no reason to suppose that event notifications aren't every bit as reliable as method calls, because that's really all they are - method calls indirected via a delegate. Do you really write your programs assuming that any time you call a method, that method call might not get through?

That degree of paranoia would make sense in a distributed scenario, where of course remoted method calls are intrinsically unreliable, and you do need something heavyweight for reliable delivery. But it's generally reckoned to be a bad idea to use events across process - they are really designed to be used in-process. And in-process, there's just no need for paranoia about whether a call will get through - if my process is alive, method calls will succeed. If my process has hung, well, that's pretty much the end for that process.

Are there scenarios where an event subscriber might be prepared to make the sacrifice of being thread-safe in exchange for being allowed to take a long time to handle the event without blocking other handlers? Of course there are. Are there scenarios in which that looks like a very unattractive trade off? Yes indeed.

While it is possible to come up with use cases for events that meet the assumptions you seem to be making, that's by no means an exhaustive list of all possible uses of event handling.

Consider data binding for example. This relies entirely on synchronous execution of event handlers for proper functioning. Raising property change notifications asynchronously would wreak havoc there.



Ian: - "If I need to be able to notify multiple subscribers where those subscribers are flakey, then maybe events simply aren't the right mechanism? "

Roy: "If you need reliable messaging, and your component should be coupled with the subscribers, yes, that's not the model for you. This model is right for when you can't know in advance who your subscribers will be, and have no control over them (that is, assume they all throw exceptions or take a long time to process, because you can't prove they won't). "

But there are plenty of examples of event sources that *do* impose the restriction that the handler must not take a long time. Windows Forms is full of them. If your event handler blocks, the applications will freeze. And as it happens, your examples here also impose some restrictions on handlers.

You can't avoid coupling entirely. And arguably, your final design entails much more egregious coupling between event source and handler than your original 'innocent' example.

It's just not possible to write an event source that imposes no restrictions on event handlers. Your use of async delegates here imposes an extremely heavy restriction on the event handler: must not care which thread the event is raised on. If you wrote a Windows Forms control that way, you'd cause trouble - everyone expects event notifications from a Control to arrive on the UI thread because that's how all the built-in controls work, and because it's much more hard work to deal with event sources that don't work this way.


The basic problem is that event sources don't operate in a vacuum. You need to consider the application model. (What's the application-wide threading model? The application-wide error handling model?) You need to consider what constraints you are going to impose on your event handlers - there will always be some. You also need to consider what constraints the handlers may want to impose on the source.

To start from the point of view that there could ever be just one correct way in which to write event sources is a flawed assumption. There are many viable and very different ways in which to use events in .NET. You have illustrated just one of them. Yours is by no means the only way, and is demonstrably the wrong way for certain important event-based scenarios. (E.g., your approach is badly broken for raising events from a Windows Forms control.)

In short, your statement:

"When your componenet fires an event it should *never in a million years* care what any of the subscribers do with the event. "

is a pipe dream.
Sunday, January 09, 2005 9:01 AM by Roy Osherove

# re: Defensive event publishing in .NET – Part I

Ian, let me start with the end of your reply:

“To start from the point of view that there could ever be just one correct way in which to write event sources is a flawed assumption. There are many viable and very different ways in which to use events in .NET. You have illustrated just one of them. Yours is by no means the only way, and is demonstrably the wrong way for certain important event-based scenarios. (E.g., your approach is badly broken for raising events from a Windows Forms control.)
In short, your statement:
"When your componenet fires an event it should *never in a million years* care what any of the subscribers do with the event. "
is a pipe dream.”

- I never said there is only one way, I stated that this approach is preferable for the “fire and forget” kind of publishing that we want to achieve. Truly, there are cases where this does not work. However, as I stated in another comment, you can (and do) have both an async and standard “Fire” method on the EventsHelper. The standard one can be called when you want sync invocation. Everything I’ve written here prescribes to the “fire and forget” scenario which is the most widely used scenario for event sources in your components that I know of. There are others, but they are not the issue for this article.

“Consider the specific case of exception handling - are you saying that Windows Forms takes the wrong approach here? It has an exception handler in its event processing loop. This means that if an event handler allows an exception to propagate back to the event source, there is a centralized mechanism for dealing with this.”

- I think it’s flawed in that the event invocation loop stops at its tracks right there, and that you “automatically” are stopped without notification. Sometimes that’s what you want, more often it’s not. The thing is, you can’t control it unless you specifically loop on the invoation list and decide what to do there.
Would you agree that if 3 subscribers get the event, and 7 don’t that’s a flaw in your program(There are scenarios which call for this behaviour, but mostly, this is not what you want)? If someone got the event, everyone should get it. Or you should at least be informed that they didn’t get it.

“(So long as event sources don't attempt to swallow the exception. The code you show here would fail to operate correctly in this scenario.) “

The point is that I don’t know nor care if they swallow the exception or not. If I have a logger that listens for the event, it’s a non-priority for my component to know whether the logger did it’s job, how long it takes to write to the log file, if it threw an exception or what not. That’s classic fire and forget. Now assume I have multiple loggers, I want them all to get the event regardless how each one operates. If one fails and that means others won’t get the event, you’re not just coupling the event source to the failed handler, you’re also coupling the *other* subscribers to all the other subscribers in your notification list. Like I said – usually a no no in a fire and forget scenario.

”Note that this particular aspect of the way events are handled in Windows Forms is ENTIRELY compatible with your stricture that an event source shouldn't care what the event handler does - controls in Windows Forms don't need to do anything special to enable this to work - they just let the exception propagate up. “

- That’s because usually events are thrown on the main GUI thread anyway. And remember that now you have full control over your event subscribers so you can make sure you don’t “hang” the application as you listen for events. I mean, you don’t want to do that on purpose, do you?

”In fact if you follow your own advice - that an event source shouldn't make assumptions about the event handler - then surely you MUST NOT swallow exceptions like you are doing. By swallowing the exception, you are making the assumption that the exception was unimportant - sure you need to know a lot about the code that threw the exception to be able to make that decision! “
- I think that’s the wrong approach. Because I can’t assume anything about the code I have no idea what kind of exceptions it could throw, nor how I should handle them. Suppose that a logger threw a “WriteLogException” in the event handler and was bad enough not to catch it on its own. What is my event source supposed to do with that exception other than to make sure it does not interfere with propagating the event to the rest of the subscribers? (again – this is the case for fire and forget).

”I think you are assuming a very specific use case for delegates and events here. The truth is that there are many different behaviours that an event source might reasonably implement for exceptions, depending on how you are using events. “

- exactly – I’m assuming this is a fire and forget model, nothing more nothing less.

”But I think that swallowing the exception is pretty much the wrong thing to do in the majority of circumstances. At a bear minimum, it should log some kind of diagnostic trace. “
- That’s possible and arguable a good idea, but it has to be implemented on a per application/component basis. For example – how would you log that a logger that tried to log your event has failed? By raising another event? By making an internal logger? How would you know *not* to log a logger failure event? You’d have to do some serious hoop jumping in order to verify what you want pr don’t want to log. All I’m saying is that it’s possible, but needs thought.


”It's not clear what you think a "standard callback" is. In Win32, the term callback typically refers to a single function callback, so it doesn't even make sense to talk of multiple subscribers. “

- I’m referring to the logical callback term. There are many ways to implement asynchronous or event based execution. Firing events is just one of those. You could also except an interface of the subscriber and invoke methods on it directly from the event source. You could also send the event source to the subscriber to create a “push-pull” model where the subscriber “pulls” the event stack from the source. These are all valid mechanisms. I would refer to the term callback logically as a way to invoke methods and follow them invocation through to the end (making sure they are finished, getting a value back, etc.). Although events are using a callback mechanism technically, the fire and forget model I think of does not have this notion of callback (i.e it does not care what happens after raising the event).

- Again, you seem to have a very specific use of the event/delegate mechanism in mind here: why are you assuming that I probably don't care whether the message got to all the subscribers? Given that the under the covers, events are raised by calling functions through delegates, it's certainly possible for me to know when the handlers have finished.
- possible, but logically that would be wrong for the fire/forget model. Just like it would be wrong to invoke private methods of a class using reflection, even though you can do that too.

“So who are you to declare that nobody is allowed to design a system that takes advantage of this? (Especially when there are examples of systems that do depend on this very feature in the .NET Framework already.) “
- I am saying that this holds water for a fire/forget model. For that I would as a rule try to stay clear of such assumptions on the event handlers my code sends messages to. Other thatn that I’m a developer such as yourself :)

”Well now you're changing the subject - the fact that certain static data is never collected is entirely unconnected with how you do event notification. Using the [OneWay] attribute will make absolutely no difference to that. And everything else will get collected whether you use [OneWay] or not. “

- The subject got changed for me when you claimed that the GC will take care of the resources. The fact is that there is one delegate that will be held in memory – the on inside the EventHelper class that is supposed to call the InvokeDelegate method. As such, it will hold information about the past calls, unless you put a [OneWay] attribute on the event handler for that delegate (which is “InvokeDelegate”). And yes, this has nothing to do with the defensive event strategy mentioned in the article. It’s just a technical problem that is resolved and must be mentioned.

”My point was that the use of the [OneWay] attribute doesn't actually contribute anything useful when it comes to reclamation of resources - the resource handling behaviour is unaffected by this attribute.
- I think you’re wrong. The memory leak isn’t a “leak” really, just a resource hog that gets bigger as the delegates are called time and time again. If the delegates are not claimed by the GC (because they are used in a system that is up 24/7 that could be a problem. The attribute solves our problem in that It rids us of the need to save the call information.

[About not having to call EndInvoke]
”This is unequivocally wrong!
You MUST call EndInvoke whenever you call BeginInvoke, even if you don't care about the results. That is the whole rule. The documentation is clear about this. (At least it is now.) “

- I beg to differ. I know you won’t believe me, so I’ll just quote Don Box’s Essential .Net part 1 on async execution:
-----snip------
“Technically, it is legal to omit the call to EndInvoke if the results of the call are not important. This mode of invocation is sometimes called fire-and-forget, or one-way invocation. One typically uses this invocation style only with methods that do not have a return value and have no pass-by-reference parameters. One also uses this invocation style only when one can safely ignore method failure, because any exceptions thrown by the target method will be swallowed by the CLR in fire-and-forget scenarios”
-----snip-------


”The documentation for OneWayAttribute says nothing about making EndInvoke optional. So there is no reason to suppose that applying [OneWay] will make it clean everything up for you. “

- that’s not why I’m using it, and that’s not what its for. It’s only for the sake of suppressing exceptions from serializing, and from preventing various other data to be saved in tot her delegate making the call. It has nothing to do with EndInvoke.

”f you don't hold onto the call object (IAsyncResult) the GC will detect that it's unreachable, and that will mean all the resources it allocated are also now unreachable. Finalizers run, objects are collected, the resources are now freed. “
- which is not the case with my “AsyncDelegate inside the events helper class.


”If you want to be robust for the future, you *must* call EndInvoke. Whether you apply [OneWay] or not.”
- see my reply on this comment earlier quoting Don Box.

”Again, you're defining arbitrary restrictions on the use of the event mechanism. There are many viable uses, and you're just characterising a subset. “
- True, there are other scenarios, but that’s what this article is about – fire and forget.

”In-process, there is no reason to suppose that event notifications aren't every bit as reliable as method calls, because that's really all they are - method calls indirected via a delegate. Do you really write your programs assuming that any time you call a method, that method call might not get through? “
- Not the same thing. When I call a method I can assume that if something bad happens, I know about it using an exception. If not, I also know in advance that some method does not throw exceptions. In any case – I know what to expect. When firing events – I have no idea whether I will get an exception, or what will happen when I do. Actualy I know that in any case of exception, the events will stop firing. That’s bad design. So this is a way to overcome that. Just like if you get an exception with standard method calls you want to either catch it or pass it on, I want to be able to do the same thing.

“That degree of paranoia would make sense in a distributed scenario, where of course remoted method calls are intrinsically unreliable, and you do need something heavyweight for reliable delivery. But it's generally reckoned to be a bad idea to use events across process - they are really designed to be used in-process. “

- not the scenario we’re talking about here.

“And in-process, there's just no need for paranoia about whether a call will get through - if my process is alive, method calls will succeed. If my process has hung, well, that's pretty much the end for that process. “

- Would you accept a state where if one method threw an exception you knew that calling other methods would succeed? That’s the case here. You at least want to have control on the situation.

Are there scenarios where an event subscriber might be prepared to make the sacrifice of being thread-safe in exchange for being allowed to take a long time to handle the event without blocking other handlers? Of course there are. Are there scenarios in which that looks like a very unattractive trade off? Yes indeed.

- like I said – you can accommodate for both scenarios using the EventsHelper class.

”While it is possible to come up with use cases for events that meet the assumptions you seem to be making, that's by no means an exhaustive list of all possible uses of event handling. “

- true

“But there are plenty of examples of event sources that *do* impose the restriction that the handler must not take a long time. Windows Forms is full of them. If your event handler blocks, the applications will freeze. And as it happens, your examples here also impose some restrictions on handlers. “

- and you normally don’t want your program to freeze, right? That’s the same case for the events helper

“You can't avoid coupling entirely. And arguably, your final design entails much more egregious coupling between event source and handler than your original 'innocent' example. “
- The coupling is to the delegates, not to the targets. It must be done in order to accommodate for the lacking features in the event model today for fire-forget scenarios.
Sunday, January 09, 2005 2:29 PM by tal

# re: Defensive event publishing in .NET – Part I

the
try(

}

catch

{}

is a bad way to solve the callee execution problems.
and of course it is a performance pennalty.

I believe there is a better way to know if the async call finished correctly(To query it - after some time)

There is also a mix between the async world and sync world.
Do i really want to create a new thread for each event firing? and what if i call it 10000 times?

Do i know my subscribers ?
This generic Solution has many drawbacks in order to get for the pure goal of being Generic


Do i really want to create an
Tuesday, January 11, 2005 12:31 AM by Eric

# re: Defensive event publishing in .NET – Part I

A couple of notes, based on my own recent experience:

1. BeginInvoke uses the threadpool. What happens if one of your subscribers never returns (intentionally or not; maybe they deadlocked)? After 25 (per processor) BeginInvokes, all of your events -- even to other subscribers have effectively been DOSed.

One way around this would be to spin off a separate Thread (not a threadpool thread). Obviously it's still possible to DOS that situation, but it will take longer, and be easier to debug (since you'll see the absurd number of threads in Task Manager etc, rather than just having the events mysteriously stop). Alternatively you could implement a timeout and Abort any thread that took an absurdly long time to finish.

2. I can think of one situation where you might care about detecting "dead" clients. If you're a remoting server and you're raising remoted events back to the client, it might be useful to detect that a method call threw a remoting-related exception (such as a SocketException) and remove that subscriber, log the error, etc. Of course, removing the subscriber can be somewhat tricky given that only the class declaring the event can modify the subscriber list, at least without a little additional legwork. I may write up the solution we're using and post it on my site, as it seems to be working out rather well.
Friday, January 14, 2005 12:22 PM by TrackBack

# re: Raising C# events doesn't feel right (and seems to have problems too)

Sunday, January 16, 2005 2:34 AM by TrackBack

# re: Events, Delegate and Multithreading

Thursday, April 07, 2005 3:17 PM by TrackBack

# Defensive Event Publishing for Remoting

Some possible additions to Roy Osherove's comments on Defensive Event Publishing in .Net, with special attention to some performance scenarios introduced by Remoting.
Thursday, April 07, 2005 11:00 PM by TrackBack

# Defensive event publishing, a different approach

Tuesday, May 23, 2006 9:30 AM by Herman van der Blom - sr. software architect

# re: Defensive event publishing in .NET – Part I

Thanx, this was just where i was looking for. I have a windows service which is capable of sending messages with remoting to listeners with events. If one of these messages fails it has to be logged and the service is continuing delivering its messages to the other listeners. After study of the logged error i make sure these exceptions will not happen again. But thats why defensive events are a very good way of programming. In the ideal world everything is always running fine, but we all know this is not the case. So i want to make sure i catch all glitches the right way, and i think this is a very good way.
Thursday, February 08, 2007 2:34 AM by damien

# re: Defensive event publishing in .NET – Part I

Im an advocate of the fail-fast philosphy on exceptions.

I absolutely never want to gooble up exceptions the way you proposed in your delegate invoke with try/catch.

Unless your program recognises exactly what the exception is and can take steps to rectify the situation, it should fall over in a heap.

Tuesday, April 24, 2007 7:48 AM by obiwanjacobi

# re: Defensive event publishing in .NET – Part I

If you call every delegate asynchronously, you hit the thread pool pretty hard if you have a lot of subscribers (and thread pool resources are precious ;-).

As an alternative you could consider calling the FireClickedEvent asynchronously. That way you only eat up 1 thread of the thread pool. This is of course only an option if the event is not too time-sensitive and subscriber would still get predictable/expected behavior when their handler is called with a certain delay...