¿Se llama a los suscriptores del evento en orden de suscripción?


¿Es seguro asumir que los suscriptores de eventos son llamados en orden de suscripción?
Ejemplo:

void One(object sender, EventArgs e) {}
void Two(object sender, EventArgs e) {}

event EventHandler foo;

foo += One;
foo += Two;

¿Siempre se llama a One() antes de Two() cuando se dispara el evento?

Editar:
Por supuesto que no deberías confiar en ello, estaba pensando. La idea era que los delegados multicast son similares al patrón de COMANDOS. Así que me preguntaba. Normalmente usaría una colección que mantiene el orden de los comandos para que pueda deshacer / rehacer / lo que sea.

Author: EricSchaefer, 2008-12-17

5 answers

Dado que la implementación, sí, siempre se llamarán en ese orden.

Si el evento realmente utiliza alguna forma extraña y maravillosa de manejar las suscripciones, podría hacer cosas diferentes, pero las implementaciones "normales" harán lo correcto.

Para ser claro, suscribirse a un controlador de eventos solo significa invocar la parte "agregar" apropiada de un evento. Si el evento maneja esto haciendo algo como:

myHandler += value;

Que se traduce en

myHandler = Delegate.Combine(myHandler, value);

Y Delegado.Combine garantiza el pedido. Sin embargo, si usted tuvo un evento como este:

private LinkedList<EventHandler> eventHandlers = new LinkedList<EventHandler>;

public event EventHandler Foo
{
    add
    {
        eventHandlers.AddFirst(value);
    }
    remove
    {
        // do stuff here too
    }
}

Y luego disparó el evento haciendo algo como:

foreach (EventHandler handler in eventHandlers)
{
    handler(this, EventArgs.Empty);
}

Entonces los manejadores serían llamados en el orden inverso.

Resumen: Para todos los eventos sanos, puede confiar en el orden. En teoría, los eventos pueden hacer lo que quieran, pero nunca he visto un evento que no mantenga el orden apropiado.

 37
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-17 18:23:01

Preste mucha atención a las advertencias dadas por Jon Skeet - "Dada esa implementación...". En otras palabras, haga el más mínimo cambio(múltiples hilos, otros manejadores, etc.) y corre el riesgo de perder la invariancia de orden de ejecución.

Haga NO confíe en el orden de eventos. Todos los despachos de eventos deben ser lógicamente independientes, como si estuvieran ocurriendo en paralelo. Los eventos son acciones lógicamente independientes.

Voy a ir un paso más allá, y afirmar que si usted tiene que asumir una orden para eventos disparando, tiene un defecto de diseño grave y / o está haciendo un mal uso de los eventos.

 22
Author: Steven A. Lowe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-17 19:02:38

Incluso si se llaman en el orden correcto, intentaría no escribir código que dependa de que se haya disparado un delegado anterior para que funcione correctamente.

Si Two() depende de algo que One() está haciendo, entonces adjunte un único delegado que llame a los dos métodos en el orden correcto, o haga que Two() invoque a One() cuando sea necesario.

 11
Author: Paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-17 13:02:56

La respuesta rápida sería "No es asunto tuyo":)

Un evento es asíncrono por naturaleza. Esto significa que usted no está esperando que un evento sea disparado o esperando que ocurra en un momento dado. Simplemente suceden y luego tomas acción. Querer saber ' cuándo 'o tratar de averiguar' cómo ' va a romper esta naturaleza.

Tal vez en este caso usted no necesita un enfoque basado en eventos para hacer las cosas?

Lo que Jon Skeet dijo es técnicamente correcto para el implementación actual, pero tal vez no lo hará en c#8.5 o VBasic 15.0. Confiar en los detalles de la implementación siempre va a hacer más daño que bien.

 4
Author: Trap,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-17 19:03:09

En general, se espera que los suscriptores de eventos se comporten independientemente unos de otros. No debería hacer ninguna diferencia si se invocan en orden de suscripción, orden inverso de suscripción o en orden aparentemente aleatorio que varía arbitrariamente cada vez que se plantea el evento. Los suscriptores no deben preocuparse por otros suscriptores que se ejecutan antes o después de ellos.

En algunos casos, sin embargo, los eventos pueden ser usados en contextos donde tal orden es importante. Controladores de eventos se puede pasar un objeto mutable, y se espera que haga uso de las mutaciones del controlador anterior de ese objeto. En tal caso, si el funcionamiento significativo de los eventos requiere que se realicen en un orden particular, y siempre que se hayan cumplido los requisitos documentados para los suscriptores, se debe esperar que los eventos se ejecuten en el orden dado.

 0
Author: supercat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-27 16:16:12