2011-11-21 23 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) 

出於這個原因,如果你是編碼複雜的多線程代碼的事件,你應該在代碼防守使得事件燒成後你認爲你已經取消訂閱是沒有問題的。

這些細微差別不會影響單線程代碼。