man*_*g18 23 c# multithreading delegates thread-safety
如果你有一个带有委托成员变量的类实例,并且多个线程调用该委托(假设它指向一个长时间运行的方法),是否存在任何争用问题?
你需要锁定委托还是每个线程调用委托指向的方法是否安全,因为每个线程都有自己的调用堆栈?
Bri*_*eon 24
关于代表的调用,答案是肯定的.
调用委托是线程安全的,因为委托是不可变的.但是,您必须确保首先存在委托.根据所需的安全级别,该检查可能需要一些同步机制.
例如,以下内容可能会抛出一个NullReferenceExceptionif SomeDelegate由null检查和调用之间的另一个线程设置为null.
if (SomeDelegate != null)
{
SomeDelegate();
}
Run Code Online (Sandbox Code Playgroud)
以下是更安全一点.在这里,我们正在利用委托是不可变的这一事实.即使另一个线程修改SomeDelegate了代码也是为了防止这种麻烦NullReferenceException.
Action local = SomeDelegate;
if (local != null)
{
local();
}
Run Code Online (Sandbox Code Playgroud)
但是,如果SomeDelegate在另一个线程中为其分配了非空值,则可能导致委托永远不会被执行.这与微妙的记忆障碍问题有关.以下是最安全的方法.
Action local = Interlocked.CompareExchange(ref SomeDelegate, null, null);
if (local != null)
{
local();
}
Run Code Online (Sandbox Code Playgroud)
关于委托引用的方法的执行,答案是否定的.
您必须通过使用同步机制提供自己的线程安全保护.这是因为CLR不会自动为代理的执行提供线程安全保护.可能的情况是,该方法不需要任何进一步的同步以使其安全,特别是如果它从不访问共享状态.但是,如果该方法从共享变量读取或写入,那么您将不得不考虑如何防止来自多个线程的并发访问.
直接来自MulticastDelegate的文档:
此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的.任何实例成员都不保证是线程安全的.
该委托类包含相同的信息,所以你有它.
| 归档时间: |
|
| 查看次数: |
15803 次 |
| 最近记录: |