Sorularınızı cevaplamak için:
- Olay işleyicilerinin tümü eşzamanlı olarak uygulanıyorsa, bir olayın başlatılması iş parçacığını engeller.
- Olay işleyicileri, olaya abone oldukları sırada birbiri ardına yürütülür.
Ben de iç mekanizması eventve bununla ilgili işlemleri merak ediyordum . Bu yüzden basit bir program yazdım ildasmve uygulanmasının etrafından dolaşıyordum.
Kısa cevap
- olaylara abone olma veya olayları çağırma ile ilgili hiçbir zaman uyumsuz işlem yoktur.
- olay, aynı delege türündeki bir destek delege alanıyla uygulanır
- abone olmak ile yapılır
Delegate.Combine()
- abonelik iptali ile yapılır
Delegate.Remove()
- Çağırma, yalnızca son birleşik delegeyi çağırarak yapılır.
İşte yaptığım şey. Kullandığım program:
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();
}
}
İşte Foo'nun uygulaması:

Bir alan OnCall ve bir olay olduğunu unutmayın OnCall . Alan OnCall, kesinlikle destekleyici mülktür. Ve bu sadece bir Func<int, string>, burada süslü değil.
Şimdi ilginç kısımlar:
add_OnCall(Func<int, string>)
remove_OnCall(Func<int, string>)
- ve nasıl
OnCallçağrılırDo()
Abone Olma ve Aboneliği İptal Etme Nasıl Uygulanır?
İşte add_OnCallCIL'deki kısaltılmış uygulama. İlginç olan kısım, Delegate.Combineiki delegeyi birleştirmek için kullanmasıdır .
.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
Aynı şekilde Delegate.Removekullanılır remove_OnCall.
Bir olay nasıl başlatılır?
Çağırmak OnCalliçin Do(), arg'yi yükledikten sonra son birleştirilmiş temsilciyi çağırır:
IL_0026: callvirt instance !1 class [mscorlib]System.Func`2<int32,string>::Invoke(!0)
Bir abone bir etkinliğe tam olarak nasıl abone olur?
Ve son olarak, Mainşaşırtıcı bir şekilde, OnCallolaya abone olmak add_OnCall, Fooörnek üzerinde yöntem çağırarak yapılır .