none
Delegates and order of Invocation List..

    Question

  • I am new to C#..

    Delegates have an invocation list where we can add or delete any method and the list does the same..

    but while calling the delegate, can we reorder the invocation list?

    Meaning that can we control  the order of the invocation list in which the methods would be called??

     

    Suppose:

    Code Snippet

     

    internal delegate void Feedback(Int32 value);

     

    public sealed class Program

    {

    public static void Main()

    {

    Feedback fb = new Feedback(FeedbackToConsole);

    fb += new Feedback(FeedbackToMsgBox);

    fb += new Feedback(new Program().FeedbackToFile);

    }

    }

     

    private static void FeedbackToConsole(Int32 value)

    {

    /*Do Something*/

    }

     

    private static void FeedbackToMsgBox(Int32 value)

    {

    /*Do Something*/

    }

     

    private void FeedbackToFile(Int32 value)

    {

    /*Do Something*/

    }

     

     

    Here in the previous example, the invocation list would be in order of FeedbackToConsole, FeedbackToMsgBox, and FeedbackToFile...

     

    But If I want to call them say in reverse order then what to do???

    Can we control the calling behaviour of the invocation list??

     

    Any answers would be appreciated...

    Thanks !

    Monday, May 05, 2008 11:48 AM

Answers

  • I agree with Marc.  While you can get access to the invocation list it is really nothing more than a list of delegates (object, method pairs).  Making sense of them at runtime is meaningless.

     

    It also doesn't make much sense to control the order of event handlers.  Events are designed to be used as broadcast-type mechanisms.  The order in which handlers are called is undefined as is, technically, whether they are all called at once or one at a time.  It is ultimately up to the event implementer.  The standard implementation is to call handlers in the order they are added and sequentially but this is by no means required.

     

    If you want to control the order of execution you should use a different mechanism.  In the past prioritized events have been used where a handler can indicate its relative priority to handling an event vs other handlers.  For example a handler you wanted to call early in the process would have a higher priority than normal handlers.  This was done in COM events on occasion but I can't think of a time when it has been used in .NET.  It is, in my opinion, a hack around how eventing works. 

     

    The important thing to remember is that all handlers will be called (unless an exception occurs).  This is true even for events that are cancellable.  The handlers will be called in some order.  Therefore you can't use a handler to prevent another handler from running (at least not by default).

     

    I would recommend that if you want to control order that you only put the handler you want to call first into the event list.  This handler then invokes other handlers via its own events or via a simple delegate chain.  This gives you the ability to control invocation order.  It does get messy for anything other than 1 level of prioritization though.

     

    Michael Taylor - 5/5/08

    http://p3net.mvps.org

     

     

    Monday, May 05, 2008 12:55 PM
  •  TaylorMichaelL wrote:

    It also doesn't make much sense to control the order of event handlers.  Events are designed to be used as broadcast-type mechanisms.  The order in which handlers are called is undefined as is, technically, whether they are all called at once or one at a time.  It is ultimately up to the event implementer.  The standard implementation is to call handlers in the order they are added and sequentially but this is by no means required.


    The order in which they are called and the way they are called is documented:

    A MulticastDelegate has a linked list of delegates, called an invocation list, consisting of one or more elements. When a multicast delegate is invoked, the delegates in the invocation list are called synchronously in the order in which they appear. If an error occurs during execution of the list then an exception is thrown.


    The documentation explicitly states that the delegates (event handlers) are called synchronously in the order they were added.

    Events in .NET are implemented using MulticastDelegate, and this fact is also documented.

    I do agree that there shouldn't be a need to change the order of execution, and if there is, there must something wrong with the architecture of the application, IMHO.


    Monday, May 05, 2008 1:13 PM

All replies

  • I'm fairly confident that invocation happens in the order they are added. If you want them in a particular order, then add them in that order. It would be hard to inspect an invocation list and make sensible decisions on it (you have a methodinfo, but that isn't always too helpful).

    This is one of the reasons it is preferable to override virtual methods to extend subclass functionality - you have complete control of the execution order, as you choose when (and if) to call "base".

    Monday, May 05, 2008 12:42 PM
  • You should retrieve each delegate by calling GetInvocationList() and then call DynamicInvoke() to execute the delegate methods.

    The following example will call the delegates in reverse order:

    Delegate[] delegates = fb.GetInvocationList();

    for (int i=delegates.Length-1;i>=0;i--)
        delegatesIdea.DynamicInvoke(0);
    Monday, May 05, 2008 12:50 PM
  • I agree with Marc.  While you can get access to the invocation list it is really nothing more than a list of delegates (object, method pairs).  Making sense of them at runtime is meaningless.

     

    It also doesn't make much sense to control the order of event handlers.  Events are designed to be used as broadcast-type mechanisms.  The order in which handlers are called is undefined as is, technically, whether they are all called at once or one at a time.  It is ultimately up to the event implementer.  The standard implementation is to call handlers in the order they are added and sequentially but this is by no means required.

     

    If you want to control the order of execution you should use a different mechanism.  In the past prioritized events have been used where a handler can indicate its relative priority to handling an event vs other handlers.  For example a handler you wanted to call early in the process would have a higher priority than normal handlers.  This was done in COM events on occasion but I can't think of a time when it has been used in .NET.  It is, in my opinion, a hack around how eventing works. 

     

    The important thing to remember is that all handlers will be called (unless an exception occurs).  This is true even for events that are cancellable.  The handlers will be called in some order.  Therefore you can't use a handler to prevent another handler from running (at least not by default).

     

    I would recommend that if you want to control order that you only put the handler you want to call first into the event list.  This handler then invokes other handlers via its own events or via a simple delegate chain.  This gives you the ability to control invocation order.  It does get messy for anything other than 1 level of prioritization though.

     

    Michael Taylor - 5/5/08

    http://p3net.mvps.org

     

     

    Monday, May 05, 2008 12:55 PM
  •  TaylorMichaelL wrote:

    It also doesn't make much sense to control the order of event handlers.  Events are designed to be used as broadcast-type mechanisms.  The order in which handlers are called is undefined as is, technically, whether they are all called at once or one at a time.  It is ultimately up to the event implementer.  The standard implementation is to call handlers in the order they are added and sequentially but this is by no means required.


    The order in which they are called and the way they are called is documented:

    A MulticastDelegate has a linked list of delegates, called an invocation list, consisting of one or more elements. When a multicast delegate is invoked, the delegates in the invocation list are called synchronously in the order in which they appear. If an error occurs during execution of the list then an exception is thrown.


    The documentation explicitly states that the delegates (event handlers) are called synchronously in the order they were added.

    Events in .NET are implemented using MulticastDelegate, and this fact is also documented.

    I do agree that there shouldn't be a need to change the order of execution, and if there is, there must something wrong with the architecture of the application, IMHO.


    Monday, May 05, 2008 1:13 PM
  • The default implementation of events is implemented via MulticastDelegate.  There is no requirement to do so.  This is why you can override the add, get and remove handlers for events.  In some cases it is more appropriate to use another implementation and .NET is perfectly fine with this.  WinForms is a good example of this.  It uses a custom implementation for events to avoid the overhead of creating a lot of delegates.  Internally it uses Delegate so it behaves the same as other events but it could just have easily used a different implementation.

     

    It is a common mistake to assume that events and delegates are the same thing.  They aren't.  Delegates are used to implement events by default but they are not related otherwise.

     

    Michael Taylor - 5/5/08

    http://p3net.mvps.org

     

     

    Monday, May 05, 2008 1:20 PM