Search code examples
c#.netwpfmultithreadingmemory-model

Bound view model property updated in background thread; will the UI always see the updated value?


If I have some (non-volatile) data bound to the UI via a view model, and I update this data from a background thread without locking anything, and trigger a PropertyChanged event, am I guaranteed that the UI will see this update? If I am, then why?

I can see that CLRBindingWorker calls Dispatcher.BeginInvoke and thus makes sure the property is read from the UI thread. What I want to know is whether the property value will always be "fresh" in the UI thread (e.g. whether a scenario similar to http://www.yoda.arachsys.com/csharp/threads/volatility.shtml can happen).

A previous answer suggested this is indeed the case, but without any explanation.

Example:

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;
}

Solution

  • That's not an ideal explanation, but corresponding to this article the lock statement produce full fence memory barrier. The current implementation of Dispatcher.BeginInvoke use lock to update Dispatcher's queue. It means that there is full fence after field assignment and before field usage in UI thread.