我正在阅读有效的 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
等人创建了一个new每次更改时委托实例(或null
如果您取消订阅最后一个处理程序)并分配一个引用(/null
) 将该新对象添加到支持字段。这就是快照很有帮助的原因。
顺便说一句:在现代 C# 中,你可以使用TheEvent?.Invoke(....)
,它会为您执行此操作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)