[英]Is C#'s null-conditional delegate invocation thread safe?
这就是我一直写的事件提升者; 例如PropertyChanged:
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string name)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(name));
}
然而,在最新的Visual Studio中,灯泡thingamabob建议将代码简化为:
private void RaisePropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
虽然我总是赞成简化,但我想确保这是安全的。 在我的原始代码中,我将处理程序分配给变量以防止订阅者在空检查和调用之间处置的竞争条件。 在我看来,新的简化形式将遭受这种情况,但我想看看是否有人可以确认或否认这一点。
它与它替换的代码(你的第一个例子)一样是线程安全的,因为它只是使用一个隐藏变量做同样的事情。
来自MSDN:
新方法是线程安全的,因为编译器只生成一次评估PropertyChanged的代码,将结果保存在临时变量中。 您需要显式调用Invoke方法,因为没有空条件委托调用语法PropertyChanged?(e)。 有太多模糊的解析情况允许它。
https://msdn.microsoft.com/en-us/library/dn986595(v=vs.140).aspx
内部.net框架在订阅事件时使用interlock.CompareExchange。 这意味着你已经有了记忆障碍。 要保证线程安全,您需要在访问事件处理程序时使用Volatile.Read(它应用隐式获取内存屏障)
Volatile.Read(ref PropertyChanged)?. Invoke(this,new PropertyChangedEventArgs(name))
来源: CLR通过C#
其他来源: https : //codeblog.jonskeet.uk/2015/01/30/clean-event-handlers-invocation-with-c-6/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.