Sve*_*vek 1 c# multithreading thread-safety multicastdelegate
我正在寻找可能对此有更多了解的人,我的直觉告诉我答案是“不,它不是线程安全的”,但我想确定。
为了说明我的问题,我为此类提供了一些背景信息
public class MyContext
{
private readonly object _lock = new object();
public delegate bool MyDelegate(MyContext context);
private MyDelegate _multicastDelegate;
public MyContext()
{
_multicastDelegate = null;
}
public void AddDelegate(MyDelegate del)
{
lock(_lock)
{
_multicastDelegate += del;
}
}
public void RemoveDelegate(MyDelegate del)
{
lock(_lock)
{
_multicastDelegate += del;
}
}
public void Go()
{
_multicastDelegate.Invoke(this);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我在上面的示例中添加了锁,但这实际上不是我的问题的重点。
我试图更好地了解保存调用列表的数组是否是线程安全的。坦白说,我不清楚这是如何组合在一起的,可以提供一些帮助。
根据我发现的文档,唯一没有提供真正洞察力的报价如下:
MulticastDelegate具有由一个或多个元素组成的委托链接列表,称为调用列表。调用多播委托时,调用列表中的委托按照它们出现的顺序被同步调用。如果在执行列表期间发生错误,则会引发异常。
https://msdn.microsoft.com/zh-CN/library/system.multicastdelegate.aspx
提前致谢。
代表们是一成不变的。您永远不会更改代表。任何看起来可以使委托变异的方法实际上都是在创建一个新实例。
代表们是一成不变的。创建后,委托的调用列表不会更改。
因此,不必担心可以在调用委托时更新调用列表。
但是,您必须警惕的是,委托实际上可能是null。
(new MyContext()).Go();
Run Code Online (Sandbox Code Playgroud)
会导致异常。过去,您必须通过将值读入局部变量,测试它是否为null,然后使用它来调用来进行防范。现在可以更轻松地将其解析为:
public void Go()
{
_multicastDelegate?.Invoke(this);
}
Run Code Online (Sandbox Code Playgroud)