繁体   English   中英

注册c#事件是否安全?

[英]is it thread safe to register for a c# event?

具体来说,是“+ =”操作原子? 如果我使用'event'关键字,或只是一个普通的老代表,它会有所作为吗?

对于大多数类型,它是一个读取,然后是“+”运算符,然后是一个写入。 所以,它不是原子的。 我想知道代表/活动是否有特殊情况。

这种代码是必要的还是冗余的:

Action handler;
object lockObj;
public event Action Handler {
    add { lock(lockObj) { handler += value; } }
    remove { lock(lockObj) { handler -= value; } }
}

是的, 自动实现的事件上的+=-=运算符是原子的(如果库使用自定义事件处理程序,它很容易不是原子的)。 来自MSDN杂志文章.NET Matters:Event Accessors

当C#编译器为MyClass生成代码时,输​​出Microsoft®中间语言(MSIL)的行为与使用图1中的代码生成的相同。

图1扩展事件实现

 class MyClass { private EventHandler _myEvent; public event EventHandler MyEvent { [MethodImpl(MethodImplOptions.Synchronized)] add { _myEvent = (EventHandler)Delegate.Combine(_myEvent, value); } [MethodImpl(MethodImplOptions.Synchronized)] remove { _myEvent = (EventHandler)Delegate.Remove(_myEvent, value); } } ... } 

[...]

显式事件实现的另一个用途是提供自定义同步机制(或删除一个)。 您将在图1中注意到,添加和删除访问器都使用MethodImplAttribute进行装饰,该MethodImplAttribute指定应同步访问者。 对于实例事件,此属性等效于使用当前实例上的锁来包装每个访问者的内容:

 add { lock(this) _myEvent += value; } remove { lock(this) _myEvent -= value; } 

如前所述这里add处理程序是自动实现的,将执行比锁更好线程安全的方式。

在涉及事件的线程安全时,您需要更加小心的是如何调用它们。 见埃里克利珀的对这个职位在这里

触发此事件的标准模式是:

 Action temp = Foo; if (temp != null) temp(); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM