为什么这个"common" C# 中线程安全事件调用的习惯用法有效?



我正在阅读有效C#,我发现了以下模式来改进事件调用行为并使其线程安全:

public class EventSource {
private EventHandler<int> Updated;
private int counter; 
public void RaiseUpdates(){
counter++;
var handler = Updated;
if (handler != null){
handler(this, counter);
}

该书声称,由于handler的分配中有一个"浅副本",因此呼叫handler(this, counter)将呼叫所有注册的客户,即使在其中一个客户取消订阅之前但是委托不是C#引用类型吗?这个赋值难道不只是为底层委托对象创建一个新的引用吗

委托对象是不可变的,因此可以复制对它的引用。引用不可变对象的独立本地副本几乎是避免线程争用问题的黄金标准。

添加/删除事件订阅时,Delegate.Combine等会在每次更改时创建一个新的委托实例(如果取消订阅最后一个处理程序,则创建null(,并将对该新对象的引用(/null(分配给backing字段。这就是为什么快照很有用。

BTW:在现代C#中,你只需要使用TheEvent?.Invoke(....),它就可以为你做到这一点。

最新更新