微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C#委托是线程安全的吗?

如何解决C#委托是线程安全的吗?

| 如果您有一个带有委托成员变量的类实例,并且有多个线程调用该委托(假设它指向一个长期运行的方法),那么是否存在争用问题? 您是否需要锁定委托,还是每个线程都可以安全地调用委托所指向的方法,因为每个线程都有自己的调用堆栈?     

解决方法

        关于委托的调用,答案是肯定的。 调用委托是线程安全的,因为委托是不可变的。但是,您必须确保首先存在一个委托。根据所需的安全级别,此检查可能需要一些同步机制。 例如,如果在空值检查和调用之间的另一个线程将
SomeDelegate
设置为null,则以下内容可能会抛出ѭ0。
if (SomeDelegate != null)
{    
  SomeDelegate();
}
以下内容更加安全。在这里,我们正在利用委托是不可变的这一事实。即使另一个线程修改了“ 1”,也很难阻止该讨厌的“ 0”。
Action local = SomeDelegate;
if (local != null)
{
  local();
}
但是,如果在另一个线程中为
SomeDelegate
分配了非空值,则可能永远不会执行委托。这与一个微妙的内存屏障问题有关。以下是最安全的方法。
Action local = Interlocked.CompareExchange(ref SomeDelegate,null,null);
if (local != null)
{
  local();  
}
关于委托人引用的方法的执行,答案是否定的。 您将必须通过使用同步机制来提供自己的线程安全保证人。这是因为CLR不会自动为委托的执行提供线程安全保证。可能的情况是,该方法不需要任何进一步的同步即可使其安全,尤其是在永不访问共享状态的情况下。但是,如果该方法从共享变量读取或写入,则必须考虑如何防止来自多个线程的并发访问。     ,        不,它们不是线程安全的,是的,您必须自己管理并发性。     ,        直接从MulticastDelegate的文档中:   此类型的任何公共static(在Visual Basic中为Shared)成员都是线程安全的。不保证任何实例成员都是线程安全的。 Delegate类包含相同的信息,因此就可以了。     ,        修改事件不是线程安全的,但是调用委托是安全的。 由于委托是不可变的,因此它是线程安全的。请参阅此处的MSDN Delegate类备注: 从这里借来的: 在CLR Via C#中,Richter指出了有关多线程类中事件调用的一些细微之处: 委托链是不可变的。将创建一个新链来替换第一个。 零订阅者的委托链为空。 这意味着(如果您的活动是公开的)它可以随时从null转换为non-null,反之亦然。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。