c# - 注册 C# 事件是线程安全的吗?

标签 c# multithreading thread-safety

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

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

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

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

最佳答案

是的,自动实现的事件 上的 +=-= 运算符是原子的(如果一个库使用自定义事件处理程序很容易不是原子的)。来自 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.

Figure 1 Expanded Event Implementation

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. 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; }

关于c# - 注册 C# 事件是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22825117/

相关文章:

c++ - 使用 memory_order_relaxed 如何在典型架构上保证原子变量的总修改顺序?

javascript - Razor View 模型绑定(bind)使用javascript函数

c# - .Net 家伙需要一些关于 Cocoa 的信息

python - 我怎样才能杀死所有线程?

javascript - Node.js 使用哪种线程模型?

c# - 使用 `lock` 比 `SemaphoreSlim` 有什么优势?

ruby-on-rails-3 - Rails 和 MongoDB,如何插入最后一个文档并确保它是线程安全的?

c# - Dapper:ConnectionString 属性尚未初始化

c# - 在流对象c#中写入 block 并接收 block

java - java.util.Comparator.compare(T o1, T o2) 的实现应该是线程安全的吗?