Does Delegate.BeginInvoke require MemoryBarrier?

时间:2017-06-15 10:23:50

标签: c# thread-safety begininvoke

private class ParamDatas
{
    public object Param1;
    public object Param2;
}

private static void Main(string[] args)
{
    Action<ParamDatas> action = ThreadAction;
    var myParamDatas = new ParamDatas();
    var result = action.BeginInvoke(myParamDatas, null, null);

    // dosomething ...
}

private static void ThreadAction(ParamDatas paramDatas)
{
    Thread.MemoryBarrier();

    // use paramDatas ....
    // var param1 = paramDatas.Param1;
}

Is the MemoryBarrier required in this code? or BeginInvoke function will avoid dirty data?

2 个答案:

答案 0 :(得分:0)

当您致电BeginInvoke时,您正在复制myParamDatas并将该数据的副本发送给函数调用。您不需要任何内存屏障或同步机制来正确提供该值。同样,在读取值之前,需要在函数调用之前执行变量或其值的任何突变,因为此时值的读取与这些更改位于同一个线程上,因此需要观察按顺序发生。这意味着如果在调用BeginInvoke之前为该对象设置了任何值,那么这些值将在调用的函数中被观察到。

如果您在调用BeginInvoke后(在调用线程上)对引用的对象进行了任何更改,那么您需要一个适当的同步机制来确保这些更改与其他线程中对象的使用正确同步。

答案 1 :(得分:-1)

是的,需要使用MemoryBarrier(或监视/锁定)。您必须使用同步机制提供自己的线程安全保证。

调用委托是线程安全的,因为它是不可变的,但委托引用的方法的执行不是线程安全的。

直接引用文章MulticastDelegate Class关于线程安全性:“此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的。不保证任何实例成员都是线程安全的。< /强>

我希望这可以帮到你!