是C#';s null条件委托调用线程安全?
这就是我一直以来写的事件提倡者;例如,PropertyChanged:是C#';s null条件委托调用线程安全?,c#,multithreading,C#,Multithreading,这就是我一直以来写的事件提倡者;例如,PropertyChanged: public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string name) { var handler = PropertyChanged; if (handler != null) handler(this, n
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));
}
虽然我一直支持简化,但我想确保这是安全的。在我的原始代码中,我将处理程序分配给一个变量,以防止出现竞态条件,在这种竞态条件下,订阅者可能在null检查和调用之间被释放。在我看来,新的简化表单可能会出现这种情况,但我想看看是否有人可以确认或否认这一点。它与它所替换的代码(您的第一个示例)一样具有线程安全性,因为它只使用了一个隐藏变量,执行完全相同的操作。来自MSDN: 新方法是线程安全的,因为编译器生成代码 评估属性仅更改一次,并将结果保留在 临时变量。您需要显式调用Invoke方法 因为没有空的条件委托调用语法 属性已更改?(e)。有太多模棱两可的解析情况 允许它
在内部.net framework在订阅事件时使用interlock.CompareExchange。这意味着你已经有了记忆障碍。为了线程安全,您需要在访问事件处理程序时使用Volatile.Read(它应用隐式获取内存屏障) Volatile.Read(ref PropertyChanged)?.Invoke(这个,新的PropertyChangedEventArgs(名称)) 资料来源: 其他来源: