They are run in the order in which they are registered. RetrieveDataCompleted is a Multicast Delegates. I am looking through reflector to try and verify, and it looks like an array is used behind the scenes to keep track of everything.
Currently, they are executed in the order they are registered. However, this is an implementation detail, and I would not rely on this behavior staying the same in future versions, since it is not required by specifications.
The invocation list of a delegate is
an ordered set of delegates in which
each element of the list invokes
exactly one of the methods invoked by
the delegate. An invocation list can
contain duplicate methods. During an
invocation, a delegate invokes methods
in the order in which they appear in
the invocation list.
You can change ordering by detaching all handlers, and then re-attaching in desired order.
public event EventHandler event1;
public void ChangeHandlersOrdering()
{
if (event1 != null)
{
List<EventHandler> invocationList = event1.GetInvocationList()
.OfType<EventHandler>()
.ToList();
foreach (var handler in invocationList)
{
event1 -= handler;
}
//Change ordering now, for example in reverese order as follows
for (int i = invocationList.Count - 1; i >= 0; i--)
{
event1 += invocationList[i];
}
}
}
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.
I had a similar problem. In my case it was fixed very easily. I'd never seen a delegate that didn't use the += operator. My problem was fixed by having one delegate always added at the end, all the others are always added at the beginning. The OP's example would be something like:
One way to manage the order of execution of event handlers in a sequential way is to register only the first handler to the event and invoke the second handler within the first handler routine and in the second handler routine invoke the third one and so on.
The other answers have established that it's very difficult to guarantee execution order. It's probably true that the events are executed in the order registered, but it might be difficult in your program to guarantee that order. For example, I have an application where events are registered by static class constructors, and apparently C# doesn't call those constructors until the class gets utilized the first time, and who knows what order that will be in.
So, many of the solutions proposed are somewhat complicated methods of changing the order, including Naser Asadi's interesting one of re-registering events. After much thought, I came up with a much simpler approach. I decided to NOT ALTER the registration order, but rather alter what happens in each event handler.
In my application, what I'm trying to do is customize a string, but multiple event handlers might customize it differently, and I don't want to rely on potluck. Instead, each handler has a different "PRIORITY". Each time the string is updated, the priority is updated also. Other handlers can't touch it unless they have a higher priority. It's a brilliantly simple solution; you merely need a way to establish a priority for each handler.
Below is an example of one of the handlers. Note that I could create a similar class and handler for vanilla ice cream also, with a different priority, and if both chocolate and vanilla are registered for the same ice cream shop, the one with higher priority will be the one that decides what the ice cream flavor is. Note that it DOES NOT MATTER if vanilla or chocolate registers their handler first! Only the priority matters, which YOU can control.
public delegate void CustomizeStringEventHandler(Object sender, CustomizeStringEventArgs e);
public class CustomizeStringEventArgs : EventArgs {
string _description;
int _priority;
}
//-----------------------
public class ExampleChocolateIceCreamFlavorClass {
static ExampleChocolateIceCreamFlavorClass() {
DowntownIceCreamShop.LookupDescription += new CustomizeStringEventHandler(CustomizeString);
CountryIceCreamShop.LookupDescription += new CustomizeStringEventHandler(CustomizeString);
}
static void CustomizeString(object sender, CustomizeStringEventArgs e) {
string desc = "Chocolate"
int priority = 50; //priority for chocolate
if ((desc != null) && ((priority > e.Priority) || (e.Description == null))) {
e.Description = desc;
e.Priority = priority;
}
}
}