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

Are C# delegates thread-safe?(C# 委托是线程安全的吗?)
本文介绍了C# 委托是线程安全的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

If you have a class instance with a delegate member variable and multiple threads invoke that delegate (assume it points to a long-running method), is there any contention issues?

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

Do you need to lock around the delegate or is it safe for each thread to call the method the delegate points to, since each thread gets it's own call stack?

推荐答案

关于委托的调用,答案是肯定的.

调用委托是线程安全的,因为委托是不可变的.但是,您必须首先确保委托存在.此检查可能需要一些同步机制,具体取决于所需的安全级别.

Invoking a delegate is thread-safe because delegates are immutable. However, you must make sure that a delegate exists first. This check may require some synchronization mechanisms depending on the level of safety desired.

例如,如果 SomeDelegate 在 null 检查和调用之间被另一个线程设置为 null,则以下内容可能会引发 NullReferenceException.

For example, the following could throw a NullReferenceException if SomeDelegate were set to null by another thread between the null check and the invocation.

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

以下内容更安全一些.在这里,我们利用了委托是不可变的这一事实.即使另一个线程修改了 SomeDelegate,代码也很难防止讨厌的 NullReferenceException.

The following is a little more safe. Here we are exploiting the fact that delegates are immutable. Even if another thread modifies SomeDelegate the code is harded to prevent that pesky NullReferenceException.

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

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

However, this might result in the delegate never being executed if SomeDelegate was assigned a non-null value in another thread. This has to do with a subtle memory barrier problem. The following is the safest method.

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

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

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

You will have to provide your own thread-safety guarentees via the use of synchronization mechanisms. This is because the CLR does not automatically provide thread-safety guarentees for the execution of delegates. It might be the case that the method does not require any further synchronization to make it safe especially if it never access shared state. However, if the method reads or writes from a shared variable then you will have to consider how to guard against concurrent access from multiple threads.

这篇关于C# 委托是线程安全的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)