Ordre d’exécution du gestionnaire d’événement

Si je configure plusieurs gestionnaires d’événements, comme ceci:

_webservice.ResortingeveDataCompleted += ProcessData1; _webservice.ResortingeveDataCompleted += ProcessData2; 

quel ordre les gestionnaires exécutent-ils lorsque l’événement ResortingeveDataCompleted est déclenché? Sont-ils exécutés dans le même thread et séquentiellement dans l’ordre enregistré?

Actuellement, ils sont exécutés dans l’ordre dans lequel ils sont enregistrés. Cependant, il s’agit d’un détail d’implémentation, et je ne compte pas sur ce comportement pour qu’il rest le même dans les versions futures, car il n’est pas requirejs par les spécifications.

La liste d’appel d’un délégué est un ensemble ordonné de delegates dans lequel chaque élément de la liste appelle exactement l’une des méthodes invoquées par le délégué. Une liste d’appel peut contenir des méthodes en double. Lors d’un appel, un délégué appelle des méthodes dans l’ordre dans lequel elles apparaissent dans la liste d’appel .

De là: Classe de délégué

L’ordre est arbitraire. Vous ne pouvez pas compter sur les gestionnaires exécutés dans un ordre particulier d’une invocation à l’autre.

Edit: Et aussi – à moins que ce soit par curiosité – le fait que vous ayez besoin de savoir est révélateur d’un problème sérieux de conception.

Vous pouvez modifier l’ordre en détachant tous les gestionnaires, puis en les rattachant dans l’ordre souhaité.

 public event EventHandler event1; public void ChangeHandlersOrdering() { if (event1 != null) { List invocationList = event1.GetInvocationList() .OfType() .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]; } } } 

Ils sont exécutés dans l’ordre dans lequel ils sont enregistrés. ResortingeveDataCompleted est un delegates de multidiffusion . Je regarde à travers le réflecteur pour essayer de vérifier, et il semble qu’un tableau est utilisé dans les coulisses pour garder une trace de tout.

Si quelqu’un doit le faire dans le contexte d’un System.Windows.Forms.Form, voici un exemple d’inversion de l’ordre de l’événement affiché.

 using System; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Windows.Forms; namespace ConsoleApplication { class Program { static void Main() { Form form; form = createForm(); form.ShowDialog(); form = createForm(); invertShownOrder(form); form.ShowDialog(); } static Form createForm() { var form = new Form(); form.Shown += (sender, args) => { Console.WriteLine("form_Shown1"); }; form.Shown += (sender, args) => { Console.WriteLine("form_Shown2"); }; return form; } static void invertShownOrder(Form form) { var events = typeof(Form) .GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic) .GetValue(form, null) as EventHandlerList; var shownEventKey = typeof(Form) .GetField("EVENT_SHOWN", BindingFlags.NonPublic | BindingFlags.Static) .GetValue(form); var shownEventHandler = events[shownEventKey] as EventHandler; if (shownEventHandler != null) { var invocationList = shownEventHandler .GetInvocationList() .OfType() .ToList(); foreach (var handler in invocationList) { events.RemoveHandler(shownEventKey, handler); } for (int i = invocationList.Count - 1; i >= 0; i--) { events.AddHandler(shownEventKey, invocationList[i]); } } } } } 

Un MulticastDelegate a une liste liée de delegates, appelée liste d’invocation, composée d’un ou de plusieurs éléments. Lorsqu’un délégué multidiffusion est appelé, les delegates de la liste d’appel sont appelés de manière synchrone dans l’ordre dans lequel ils apparaissent. Si une erreur survient lors de l’exécution de la liste, une exception est émise.