Csharp/C#教程:C#代理是否是线程安全的?分享


C#代理是否是线程安全的?

如果你有一个带有委托成员变量的类实例,并且多个线程调用该委托(假设它指向一个长期运行的方法),是否存在任何争用问题?

你是否需要锁定委托,或者每个线程调用委托所指向的方法是否安全,因为每个线程都有自己的调用堆栈?

关于代表的调用,答案是肯定的。

调用委托是线程安全的,因为委托是不可变的。 但是,您必须确保代理首先存在。 根据所需的安全级别,该检查可能需要一些同步机制。

例如,如果SomeDelegate被null检查和调用之间的另一个线程设置为null,则以下内容可能抛出NullReferenceException

 if (SomeDelegate != null) { SomeDelegate(); } 

以下是更安全一点。 在这里,我们正在利用委托是不可变的这一事实。 即使另一个线程修改SomeDelegate ,代码也会受到阻止,以防止那令人讨厌的NullReferenceException

 Action local = SomeDelegate; if (local != null) { local(); } 

但是,如果在另一个线程中为SomeDelegate分配了一个非null值,这可能会导致委托永远不会被执行。 这与一个微妙的记忆障碍问题有关。 以下是最安全的方法。

 Action local = Interlocked.CompareExchange(ref SomeDelegate, null, null); if (local != null) { local(); } 

关于委托引用的方法的执行,答案是否定的。

您必须通过使用同步机制提供自己的线程安全保护。 这是因为CLR不会自动为代表的执行提供线程安全保护。 可能的情况是,该方法不需要任何进一步的同步来使其安全,特别是如果它永远不会访问共享状态。 但是,如果该方法从共享变量读取或写入,那么您将不得不考虑如何防止来自多个线程的并发访问。

不,他们不是线程安全的,是的,你必须自己管理并发。

直接来自MulticastDelegate的文档:

此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的。 任何实例成员都不保证是线程安全的。

Delegate类包含相同的信息,因此您可以使用它。

修改事件不是线程安全的,但调用委托是。 由于委托是不可变的,因此它是线程安全的。 请参阅此处的备注MSDN Delegate类 :

借用于此 :在CLR中通过C #Richter指出了一些关于multithreading类中事件调用的细微点:

委托链是不可变的; 创建一个新的链来替换第一个。 具有零订户的委托链为空。 这意味着(如果您的事件是公开的)它可以随时从null转换为非null,反之亦然。

上述就是C#学习教程:C#代理是否是线程安全的?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/951216.html

(0)
上一篇 2021年11月18日
下一篇 2021年11月18日

精彩推荐