简体   繁体   English

注册c#事件是否安全?

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

specifically, is the "+=" operation atomic? 具体来说,是“+ =”操作原子? does it make a difference if i'm using the 'event' keyword, or just a plain old delegate? 如果我使用'event'关键字,或只是一个普通的老代表,它会有所作为吗?

with most types, its a read, then the "+" operator, and then a write. 对于大多数类型,它是一个读取,然后是“+”运算符,然后是一个写入。 so, it's not atomic. 所以,它不是原子的。 i'd like to know if there's a special case for delegates/events. 我想知道代表/活动是否有特殊情况。

is this kind of code necessary, or redundant: 这种代码是必要的还是冗余的:

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

Yes, the += and -= operators on auto implemented events are atomic (if a library used a custom event handler it could very easily not be atomic). 是的, 自动实现的事件上的+=-=运算符是原子的(如果库使用自定义事件处理程序,它很容易不是原子的)。 From the MSDN Magazine article .NET Matters: Event Accessors 来自MSDN杂志文章.NET Matters:Event Accessors

When the C# compiler generates code for MyClass, the output Microsoft® Intermediate Language (MSIL) is identical in behavior to what would have been produced using code like that in Figure 1. 当C#编译器为MyClass生成代码时,输​​出Microsoft®中间语言(MSIL)的行为与使用图1中的代码生成的相同。

Figure 1 Expanded Event Implementation 图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); } } ... } 

[...] [...]

Another use for explicit event implementation is to provide a custom synchronization mechanism (or to remove one). 显式事件实现的另一个用途是提供自定义同步机制(或删除一个)。 You'll notice in Figure 1 that both the add and remove accessors are adorned with a MethodImplAttribute that specifies that the accessors should be synchronized. 您将在图1中注意到,添加和删除访问器都使用MethodImplAttribute进行装饰,该MethodImplAttribute指定应同步访问者。 For instance events, this attribute is equivalent to wrapping the contents of each accessor with a lock on the current instance: 对于实例事件,此属性等效于使用当前实例上的锁来包装每个访问者的内容:

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

As noted here , the add handler is auto-implemented in a thread-safe way that will perform better than a lock. 如前所述这里add处理程序是自动实现的,将执行比锁更好线程安全的方式。

What you need to be more careful of, when it comes to thread-safety on events, is how you invoke them. 在涉及事件的线程安全时,您需要更加小心的是如何调用它们。 See Eric Lippert's post on this here . 见埃里克利珀的对这个职位在这里

The standard pattern for firing this event is: 触发此事件的标准模式是:

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

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

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