Orden de ejecución del controlador de eventos

Si configuro varios manejadores de eventos, así:

_webservice.RetrieveDataCompleted += ProcessData1; _webservice.RetrieveDataCompleted += ProcessData2; 

¿en qué orden se ejecutan los controladores cuando se activa el evento RetrieveDataCompleted ? ¿Se ejecutan en el mismo hilo y secuencialmente en el orden en que se registran?

Actualmente, se ejecutan en el orden en que están registradas. Sin embargo, este es un detalle de implementación, y no me gustaría que este comportamiento se mantuviera en las versiones futuras, ya que las especificaciones no lo requieren.

La lista de invocación de un delegado es un conjunto ordenado de delegates en el que cada elemento de la lista invoca exactamente uno de los métodos invocados por el delegado. Una lista de invocación puede contener métodos duplicados. Durante una invocación, un delegado invoca métodos en el orden en que aparecen en la lista de invocaciones .

Desde aquí: Delegado de clase.

Puede cambiar el orden al separar todos los manejadores y luego volver a adjuntarlos en el orden deseado.

 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]; } } } 

Se ejecutan en el orden en que se registran. RetrieveDataCompleted es un delegado de multidifusión . Estoy mirando a través del reflector para probar y verificar, y parece que se usa una matriz detrás de escena para realizar un seguimiento de todo.

El orden es arbitrario. No puede confiar en que los controladores se ejecuten en un orden particular de una invocación a la siguiente.

Edit: Y también, a menos que sea por curiosidad, el hecho de que necesite saber es indicativo de un problema grave de diseño.

Si alguien necesita hacer esto en el contexto de un System.Windows.Forms.Form, aquí hay un ejemplo que invierte el orden del evento Mostrado.

 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 tiene una lista vinculada de delegates, denominada lista de invocación, que consta de uno o más elementos. Cuando se invoca un delegado de multidifusión, los delegates en la lista de invocación se llaman de forma síncrona en el orden en que aparecen. Si se produce un error durante la ejecución de la lista, se lanza una excepción.

    Intereting Posts