注册 ac# 事件是否线程安全?

not*_*ama 5 c# multithreading thread-safety

具体来说,“+=”操作是原子的吗?如果我使用“事件”关键字,或者只是一个普通的旧委托,这有什么不同吗?

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

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

Action handler;
object lockObj;
public event Action Handler {
    add { lock(lockObj) { handler += value; } }
    remove { lock(lockObj) { handler -= value; } }
}
Run Code Online (Sandbox Code Playgroud)

Sco*_*ain 4

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

\n\n
\n

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

\n\n

图 1 扩展事件实现

\n\n
class MyClass\n{\n    private EventHandler _myEvent;\n\n    public event EventHandler MyEvent\n    {\n        [MethodImpl(MethodImplOptions.Synchronized)]\n        add \n        { \n            _myEvent = (EventHandler)Delegate.Combine(_myEvent, value);\n        }\n        [MethodImpl(MethodImplOptions.Synchronized)]\n        remove \n        { \n            _myEvent = (EventHandler)Delegate.Remove(_myEvent, value); \n        }\n    }\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

[...]

\n\n

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

\n\n
add { lock(this) _myEvent += value; } \nremove { lock(this) _myEvent -= value; }\n
Run Code Online (Sandbox Code Playgroud)\n
\n