WPF is very similar to Windows Forms in terms of its multi threaded capabilities. While it does use multiple threads as part of the rendering pipeline as far as a user of WPF is concerned the UI is single threaded. So the old rule that we must do all of our UI updates from the main thread still applies.

In Windows Forms we would use Control.Invoke to send work back to our main thread. WPF is very similar. It provides the Dispatcher which allows us to Invoke back onto the main thread.

Its reasonably straight forward to use. We provide a delegate that we would like to run on the main thread, and ask the Dispatcher to run it using either Invoke (for synchronous running) or BeginInvoke (for async running).

Consider the following example. We have a simple window with a label and on startup we create a thread that simulates a long running task (in this case calculating Pi, with a few sleeps to slow it down). The thread will then use the Dispatcher to periodically update the UI with its progress.

Xaml:

<Window x:Class="DispatcherApp.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="111" Width="535">
    <Grid>
        <Label Margin="13,22,19,24" Name="label1">Label</Label>
    </Grid>
</Window>

C#:

using System;
using System.Windows;
using System.Threading;

namespace DispatcherApp
{
    delegate void UpdateTheUI(string newText);

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            Thread thrd = new Thread(new ThreadStart(this.CalculatePi));
            thrd.Start();
        }

        void CalculatePi()
        {
            double res = 0.0;
            for (int i = 0; i < 20; i++)
            {
                Thread.Sleep(1000);
                
                res += Factorial(2 * i) /
                    (Math.Pow(Factorial(i), 2) * ((2 * i) + 1) * Math.Pow(16, i));

                string piText = (res * 3.0).ToString();

                this.Dispatcher.BeginInvoke(
                    System.Windows.Threading.DispatcherPriority.Normal,
                    (UpdateTheUI)delegate(string text)
                    {
                        label1.Content = text;
                    }, piText);

            }

        }

        double Factorial(long value)
        {
            long returnVal = 1;
            for (long i = 2; i <= value; i++)
            {
                returnVal *= i;
            }
            return (double)returnVal;
        }

    }
}

Its worth noting that there are other ways to do this in WPF. The BackgroundWorker provides similar capabilities and might be more appropriate in some circumstances.