C#事件处理程序的内部工作原理是什么?

4
我猜测C#的事件处理程序具有一个监听器列表,当发送消息时会循环遍历该列表。我的问题是它在内部是如何工作的。在循环遍历之前,它是否复制了列表?如果是这样的话,如果有人在列表被复制后但尚未收到消息时注销自己,会发生什么?
即使已注销,它仍然会收到消息吗?
1个回答

6
委托是不可变的,因此在调用委托时,订阅者列表已知且固定。订阅或取消订阅替换了支持该事件的委托。
这确实意味着在多线程场景中,您可能会在取消订阅后收到事件,因为:
1. 委托已经在被调用的过程中。 2. 委托的快照已经被获取以进行调用目的
对于第二点,我指的是通常的模式(防止调用期间出现空引用):
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)

因此,如果你正在编写与事件相关的复杂多线程代码,你应该采用防御性编码方法,以便在你认为已经取消订阅后触发的事件不会成为问题。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接