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

注册c#事件是否线程安全?,c#,multithreading,thread-safety,C#,Multithreading,Thread Safety,具体来说,“+=”操作是原子的吗? 如果我使用'event'关键字,或者仅仅是一个普通的旧委托,会有区别吗 对于大多数类型,它是一个读操作,然后是“+”操作符,然后是写操作。所以,它不是原子的。我想知道代表/活动是否有特殊情况 这种代码是必要的还是多余的: Action handler; object lockObj; public event Action Handler { add { lock(lockObj) { handler += value; } } remove

具体来说,“+=”操作是原子的吗? 如果我使用'event'关键字,或者仅仅是一个普通的旧委托,会有区别吗

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

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

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

是的,自动实现的事件上的
+=
-=
操作符是原子的(如果库使用自定义事件处理程序,它很容易就不是原子的)。来自MSDN杂志的文章

当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,指定访问器应为 已同步。对于实例事件,此属性等效于 将每个访问者的内容包装为当前 实例:

add { lock(this) _myEvent += value; } 
remove { lock(this) _myEvent -= value; }
如前所述,
add
处理程序是以线程安全的方式自动实现的,其性能优于锁

当涉及到事件的线程安全时,您需要更加小心的是如何调用它们。请参阅Eric Lippert关于此的帖子

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

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

+1可能重复,这是一个很好的例子,说明了为什么要避免锁定状态对象,例如
lock(_eventSource){…}