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