เพื่อตอบคำถามของคุณ:
- การเพิ่มเหตุการณ์จะบล็อกเธรดหากตัวจัดการเหตุการณ์ทั้งหมดถูกนำไปใช้พร้อมกัน
- ตัวจัดการเหตุการณ์จะถูกดำเนินการตามลำดับทีละรายการตามลำดับที่สมัครเป็นสมาชิกเหตุการณ์
ฉันก็อยากรู้เกี่ยวกับกลไกภายใน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อินสแตนซ์