अपने सवालों के जवाब देने के लिए:
- यदि कोई घटना ईवेंट हैंडलर सभी सिंक्रनाइज़ किए गए हैं, तो किसी घटना को उठाना थ्रेड को ब्लॉक करता है।
- घटना संचालकों को क्रमिक रूप से निष्पादित किया जाता है, एक के बाद एक, क्रम में उन्हें घटना के लिए सदस्यता दी जाती है।
मैं भी आंतरिक तंत्र 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();
}
}
यहाँ फू का कार्यान्वयन है:
ध्यान दें कि एक क्षेत्र 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
।