C#eventhandler如何在内部工作?

时间:2011-11-21 09:40:14

标签: c# event-handling

我猜C#eventhandler有一个监听器列表,它在发送消息时通过列表循环。我的问题是这是如何在内部工作的。它是否在循环之前制作列表的副本,如果是这样,如果有人在复制列表之后取消注册但尚未收到消息,会发生什么。

即使它已取消注册,它仍会收到消息吗?

1 个答案:

答案 0 :(得分:6)

委托是不可变的,因此当您调用委托时,已知并修复了订阅者列表。订阅或取消订阅替换支持该活动的代表。

这确实意味着在多线程场景中,您可以在取消订阅后收到事件,因为:

  1. 委托已经被调用
  2. 已经为调用的目的获取了代表的快照
  3. by 2,我的意思是通常的模式(为了防止在调用期间出现null-ref):

    var handler = SomeEvent;
    // <===== another thread could unsubscribe at this point
    if(handler != null) handler(sender, args); // <== or part way through this invoke
    // (and it either case, have the event trigger even though they think they have
    // unsubscribed)
    

    出于这个原因,如果您使用事件编写复杂的多线程代码,则应该采取防御性编码,以便在之后触发您认为已取消订阅的事件不是问题。

    这些细微差别并不会影响单线程代码。