Untuk menjawab pertanyaan Anda:
- Memunculkan acara memang memblokir utas jika semua penangan acara diterapkan secara sinkron.
- Penangan acara dijalankan secara berurutan, satu demi satu, dalam urutan mereka berlangganan acara tersebut.
Saya juga ingin tahu tentang mekanisme internal eventdan operasinya yang terkait. Jadi saya menulis program sederhana dan terbiasa ildasmmelihat-lihat implementasinya.
Jawaban singkatnya adalah
- tidak ada operasi asinkron yang terlibat dalam berlangganan atau menjalankan acara.
- acara diimplementasikan dengan bidang delegasi dukungan dari jenis delegasi yang sama
- berlangganan selesai dengan
Delegate.Combine()
- berhenti berlangganan selesai dengan
Delegate.Remove()
- Pemanggilan dilakukan dengan hanya memanggil delegasi gabungan terakhir
Inilah yang saya lakukan. Program yang saya gunakan:
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();
}
}
Berikut implementasi Foo:

Perhatikan bahwa ada lapangan OnCall dan acara OnCall . Lapangan OnCalljelas merupakan properti pendukung. Dan itu hanya Func<int, string>, tidak ada yang mewah di sini.
Sekarang bagian yang menarik adalah:
add_OnCall(Func<int, string>)
remove_OnCall(Func<int, string>)
- dan bagaimana
OnCalldipanggilDo()
Bagaimana Berlangganan dan Berhenti Berlangganan Diterapkan?
Berikut add_OnCallimplementasi yang disingkat di CIL. Bagian yang menarik adalah digunakan Delegate.Combineuntuk menggabungkan dua delegasi.
.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
Demikian juga, Delegate.Removedigunakan dalam remove_OnCall.
Bagaimana sebuah acara dipanggil?
Untuk memanggil OnCalldi Do(), itu hanya menyebut delegasi bersambung final setelah memuat arg yang:
IL_0026: callvirt instance !1 class [mscorlib]System.Func`2<int32,string>::Invoke(!0)
Bagaimana tepatnya pelanggan berlangganan suatu acara?
Dan akhirnya, Maintidak mengherankan, berlangganan ke OnCallacara dilakukan dengan memanggil add_OnCallmetode pada Fooinstance.