绑定视图模型属性在后台线程中更新; UI会始终看到更新的值吗?

ehn*_*ark 6 .net c# wpf multithreading memory-model

如果我通过视图模型将某些(非易失性)数据绑定到UI,并且我从后台线程更新此数据而不锁定任何内容,并触发PropertyChanged事件,我保证 UI将看到此更新吗?如果我,那为什么?

我可以看到CLRBindingWorker调用Dispatcher.BeginInvoke,从而确保从UI线程中读取属性.我想知道的是,UI线程中的属性值是否总是"新鲜"(例如,是否可能发生类似于http://www.yoda.arachsys.com/csharp/threads/volatility.shtml的场景).

一个以前的答案表明这确实是这样的,但没有任何解释.

例:

public class MyViewModel : INotifyPropertyChanged
{
    // Bound to the view as <TextBlock Text="{Binding Data}" />
    private long _data;
    public long Data
    {
        get { return _data; }
        set
        {
            _data = value;
            FirePropertyChanged("Data");
        }
    }

    public MyViewModel()
    {
        new Thread(Updater).Start();
    }

    private void Updater()
    {
        while (true)
        {
            Data++;
            Thread.Sleep(1000);
        }
    }

    private void FirePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null) 
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*nov 2

这不是一个理想的解释,但与本文相对应的是,该语句lock产生完整的栅栏内存屏障。Dispatcher.BeginInvoke 的当前实现用于lock更新 Dispatcher 的队列。这意味着在 UI 线程中字段分配之后和字段使用之前存在完整的栅栏。