Para responder tu pregunta:
- La generación de un evento bloquea el hilo si todos los controladores de eventos se implementan sincrónicamente.
- Los controladores de eventos se ejecutan secuencialmente, uno tras otro, en el orden en que están suscritos al evento.
Yo también tenía curiosidad por el mecanismo interno de eventy sus operaciones relacionadas. Así que escribí un programa simple y solía ildasmhurgar en su implementación.
La respuesta corta es
- no hay ninguna operación asincrónica involucrada en la suscripción o invocación de eventos.
- El evento se implementa con un campo de delegado de respaldo del mismo tipo de delegado.
- la suscripción se realiza con
Delegate.Combine()
- darse de baja se hace con
Delegate.Remove()
- La invocación se realiza simplemente invocando al delegado combinado final
Esto es lo que hice. El programa que utilicé:
public class Foo
{
// cool, it can return a value! which value it returns if there're multiple
// subscribers? answer (by trying): the last subscriber.
public event Func<int, string> OnCall;
private int val = 1;
public void Do()
{
if (OnCall != null)
{
var res = OnCall(val++);
Console.WriteLine($"publisher got back a {res}");
}
}
}
public class Program
{
static void Main(string[] args)
{
var foo = new Foo();
foo.OnCall += i =>
{
Console.WriteLine($"sub2: I've got a {i}");
return "sub2";
};
foo.OnCall += i =>
{
Console.WriteLine($"sub1: I've got a {i}");
return "sub1";
};
foo.Do();
foo.Do();
}
}
Aquí está la implementación de Foo:

Tenga en cuenta que hay un campo OnCall y un evento OnCall . El campo OnCalles obviamente la propiedad de respaldo. Y es simplemente un Func<int, string>, nada lujoso aquí.
Ahora las partes interesantes son:
add_OnCall(Func<int, string>)
remove_OnCall(Func<int, string>)
- y como
OnCallse invoca enDo()
¿Cómo se implementa la suscripción y cancelación de suscripción?
Aquí está la add_OnCallimplementación abreviada en CIL. La parte interesante es que se utiliza Delegate.Combinepara concatenar dos delegados.
.method public hidebysig specialname instance void
add_OnCall(class [mscorlib]System.Func`2<int32,string> 'value') cil managed
{
// ...
.locals init (class [mscorlib]System.Func`2<int32,string> V_0,
class [mscorlib]System.Func`2<int32,string> V_1,
class [mscorlib]System.Func`2<int32,string> V_2)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Func`2<int32,string> ConsoleApp1.Foo::OnCall
// ...
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
// ...
} // end of method Foo::add_OnCall
Asimismo, Delegate.Removese utiliza en remove_OnCall.
¿Cómo se invoca un evento?
Para invocar OnCallen Do(), simplemente llama al delegado concatenada final después de cargar el arg:
IL_0026: callvirt instance !1 class [mscorlib]System.Func`2<int32,string>::Invoke(!0)
¿Cómo se suscribe exactamente un suscriptor a un evento?
Y finalmente, Mainno es sorprendente que la suscripción al OnCallevento se realice llamando al add_OnCallmétodo en la Fooinstancia.