System.MulticastDelegate`的线程安全吗?

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

提前致谢。

Dam*_*ver 6

代表们是一成不变的。您永远不会更改代表。任何看起来可以使委托变异的方法实际上都是在创建一个新实例。

代表们是一成不变的。创建后,委托的调用列表不会更改。

因此,不必担心可以在调用委托时更新调用列表。

但是,您必须警惕的是,委托实际上可能是null。

(new MyContext()).Go();
Run Code Online (Sandbox Code Playgroud)

会导致异常。过去,您必须通过将值读入局部变量,测试它是否为null,然后使用它来调用来进行防范。现在可以更轻松地将其解析为:

public void Go()
{
    _multicastDelegate?.Invoke(this);
}
Run Code Online (Sandbox Code Playgroud)