WPF, Data Binding & Multithreading

June 24th, 2007

While experimenting with WPF data binding mechanism today, I’ve noticed a feature which could ease the pain of following the core principle of GUI multi-threaded programming – “Thou shalt not interact with a control’s properties from a thread other than the one that created the control.”

In my little WPF databinding experiment I created a data class implementing INotifyPropertyChanged interface, and a simple WPF window with single textbox on it. My WPF window has an instance of my data class and the textbox’s Text property is bound to ‘AskPrice’ property of my data class. To be more concrete, here is the source code:
  
   Data Class:
    public class Data : INotifyPropertyChanged
    {
        private double askPrice;

        public double AskPrice
        {
            get { return askPrice; }
            set
       {
                  askPrice = value;
                  PropertyChangedEventHandler temp = PropertyChanged;
                  if (temp != null )
                  {
                     temp(this,
new PropertyChangedEventArgs(“AskPrice”));
                  }

                }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

WPF window XAML:

      xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
    Title=”Window1″ Height=”99″ Width=”140″ Loaded=”Grid_Loaded”>
   
   
 

WPF Window Code Behind:
  public partial class Window1 : Window
    {
      
        private Data data;
        //Background Thread updating the data
        private Thread dataSupplier;
        public Window1()
        {
            InitializeComponent();
            data = new Data();
            ask.SetBinding(TextBox.TextProperty, new Binding(“AskPrice”));
            dataSupplier = new Thread(new ThreadStart(this.PumpData));
           
        }
        public void PumpData()
        {
            while (true)
            {  
                Random r = new Random();
                data.AskPrice = r.NextDouble();
                Thread.Sleep(1000);
            }
        }

        private void Grid_Loaded(object sender, EventArgs e)
        {
            this.Grid1.DataContext = data;
            dataSupplier.Start();
        }
    }
}

If you’re still reading so far with your .NET 2.0/1.1/1.0 glasses, you might have noticed that ‘PumpData’ function is violating the cardinal rule of Windows GUI programming by setting the Text property (via DataBinding) on a non-GUI thread. If you port the above code to .NET 2.0 you will get the good old “InvalidOperationException was unhandled” error message. However, in .NET 3.5 this code works without any errors and you will see that your ask price is ticking nicely. It seems that WPF framework is marshalling the background thread update to the GUI thread behind scenes, but how?

The explanation starts to appear when you put a break point in “PumpData” function and debug the application. If you check the value of ‘ask.GetBindingExpression(TextBox.TextBoxProperty)’ in your watch window and expand the non-public members of it, you will see that BindingExpression has an instance of mysterious “ClrBindingWorker” class and that instance contains the ‘Dispatcher’ which is responsible from marshalling background thread calls onto GUI thread.

Watch Window

Unfortunately, when you check the MSDN or Google for “ClrBindingWorker” class, you cannot get any helpful information. As a last result, I tried Reflector to see what this undocumented class does behind the scenes. ClrBindingWorker is derived from BindingWorker class and a quick Reflector investigation reveals that it is mainly responsible from attaching binding to data item and performing the data transfer. Among its more than 20 member functions two of them seem interesting to explain behind data marshalling, “ private static object OnCompleteGetValueCallback(AsyncDataRequest adr)” and “private static object OnCompleteSetValueCallback(AsyncDataRequest adr)”. When you disassemble these:

private static object OnCompleteSetValueCallback(AsyncDataRequest adr)
{
    AsyncSetValueRequest arg = (AsyncSetValueRequest) adr;
    ClrBindingWorker worker = (ClrBindingWorker) arg.Args[0];
    worker.Dispatcher.BeginInvoke(DispatcherPriority.DataBind, CompleteSetValueLocalCallback, arg);
    return null;
}

private static object OnCompleteGetValueCallback(AsyncDataRequest adr)
{
    AsyncGetValueRequest arg = (AsyncGetValueRequest) adr;
    ClrBindingWorker worker = (ClrBindingWorker) arg.Args[0];
    worker.Dispatcher.BeginInvoke(DispatcherPriority.DataBind, CompleteGetValueLocalCallback, arg);
    return null;
}

The Dispatcher instance is used to marshal the execution of background thread call onto the UI thread!
 

 

One Response to “WPF, Data Binding & Multithreading”

  1. Anil Dhandar Says:

    Hi,

    This is a good article and has good explaination regarding how mutlithreading scenario works when two objects are created in same thread but the source is updated in other thread.

    But is this scenario possible for DependencyProperties?

    Basically two dependencyobjects being created in different threads (having different Dispatchers) and want to bind dependencyproperties of them.

    I tried creating the sample application using override for Set and Getvalue methods of DependencyObjects where CheckAccess is called. This was fooling WPF normal case, but I know this is not a good design.
    But ultimately Binding fails for such scenarios.

    Could you please suggest me alternative for the same?

    Thanks and Regards,
    Anil