c# - tiempo - que es un evento de un control
Orden de ejecuciĆ³n del controlador de eventos (7)
Si configuro múltiples controladores de eventos, así:
_webservice.RetrieveDataCompleted += ProcessData1;
_webservice.RetrieveDataCompleted += ProcessData2;
¿Qué orden ejecutan los controladores cuando se activa el evento RetrieveDataCompleted
? ¿Se ejecutan en el mismo hilo y de forma secuencial en el orden en que se registran?
La lista de invocación de un delegado es un conjunto ordenado de delegados 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 invocación .
Desde aquí: clase de delegados
Actualmente, se ejecutan en el orden en que están registrados. Sin embargo, este es un detalle de implementación, y no confiaría en que este comportamiento permanezca igual en futuras versiones, ya que las especificaciones no lo requieren.
El orden es arbitrario. No puede confiar en que los manejadores se ejecuten en un orden particular de una invocación a la siguiente.
Editar: Y también, a menos que esto sea solo por curiosidad, el hecho de que usted necesita saber es indicativo de un problema serio de diseño.
Puede cambiar el orden separando todos los manipuladores y luego volviendo a colocarlos en el orden deseado.
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];
}
}
}
Se ejecutan en el orden en que están registrados. RetrieveDataCompleted
es un delegado de multidifusión . Estoy mirando a través del reflector para probar y verificar, y parece que una matriz se utiliza detrás de las escenas para realizar un seguimiento de todo.
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<EventHandler>()
.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 de delegados vinculada, llamada lista de invocación, que consta de uno o más elementos. Cuando se invoca un delegado de multidifusión, los delegados 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.