2011-11-21 54 views
5

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

它仍然会收到消息,即使它有注销自己?

回答

6

委托是不可变的,所以当你调用委托时,订户列表是已知的并且是固定的。订阅或取消订阅取代支持该事件的代表

这确实意味着,在一个多线程的情况下,您可以后退订接收事件,因为无论:

  1. 的代表已经在被调用
  2. 的快照的过程已经获得用于目的由2调用

的代表,我的意思是通常的模式(以防止空REF杜里NG调用):

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) 

出于这个原因,如果你是编码复杂的多线程代码的事件,你应该在代码防守使得事件烧成后你认为你已经取消订阅是没有问题的。

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