เพื่อตอบคำถามของคุณ:
- การเพิ่มเหตุการณ์จะบล็อกเธรดหากตัวจัดการเหตุการณ์ทั้งหมดถูกนำไปใช้พร้อมกัน
- ตัวจัดการเหตุการณ์จะถูกดำเนินการตามลำดับทีละรายการตามลำดับที่สมัครเป็นสมาชิกเหตุการณ์
ฉันก็อยากรู้เกี่ยวกับกลไกภายในevent
และการทำงานที่เกี่ยวข้องเช่นกัน ดังนั้นฉันจึงเขียนโปรแกรมง่ายๆและใช้ildasm
เพื่อกระตุ้นการใช้งาน
คำตอบสั้น ๆ คือ
- ไม่มีการดำเนินการแบบอะซิงโครนัสที่เกี่ยวข้องกับการสมัครหรือเรียกใช้เหตุการณ์
- เหตุการณ์ถูกนำไปใช้โดยมีเขตข้อมูลผู้รับมอบสิทธิ์สำรองประเภทผู้รับมอบสิทธิ์เดียวกัน
- สมัครสมาชิกเสร็จสิ้นด้วย
Delegate.Combine()
- ทำการยกเลิกการสมัครด้วยไฟล์
Delegate.Remove()
- การเรียกใช้ทำได้โดยเพียงแค่เรียกผู้ร่วมประชุมที่รวมกันสุดท้าย
นี่คือสิ่งที่ฉันทำ โปรแกรมที่ฉันใช้:
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();
}
}
นี่คือการใช้งานของ Foo:
โปรดทราบว่ามีข้อมูล OnCall
และเหตุการณ์ เห็นได้ชัดว่าOnCall
ฟิลด์OnCall
เป็นคุณสมบัติสำรอง และมันเป็นเพียงแค่Func<int, string>
ไม่มีอะไรน่าสนใจที่นี่
ตอนนี้ส่วนที่น่าสนใจ ได้แก่
add_OnCall(Func<int, string>)
remove_OnCall(Func<int, string>)
- และวิธี
OnCall
เรียกใช้ในDo()
การสมัครสมาชิกและการยกเลิกการสมัครใช้งานอย่างไร?
นี่คือการadd_OnCall
ใช้งานแบบย่อใน CIL ส่วนที่น่าสนใจคือใช้Delegate.Combine
ในการเชื่อมต่อผู้รับมอบสิทธิ์สองคน
.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
ในทำนองเดียวกันDelegate.Remove
ใช้ในremove_OnCall
.
มีการเรียกเหตุการณ์อย่างไร?
จะก่อให้เกิดOnCall
ในDo()
มันก็เรียกผู้แทนการตัดแบ่งสุดท้ายหลังจากที่โหลดหาเรื่อง:
IL_0026: callvirt instance !1 class [mscorlib]System.Func`2<int32,string>::Invoke(!0)
สมาชิกสมัครเข้าร่วมกิจกรรมได้อย่างไร?
และในที่สุดก็Main
ไม่น่าแปลกใจที่การสมัครเข้าร่วมOnCall
กิจกรรมทำได้โดยadd_OnCall
วิธีการโทรบนFoo
อินสแตนซ์