DispatcherObject in WPF


DispatcherObject is base class for most of the WPF objects which wants to run on its own thread. That means if any object derives from DispatcherObject then that object is accessible from only DispatcherObject thread. All WPF controls and WPF forms are derived from DispatcherObject object, so we can access these controls from DispatcherObject thread which is the main thread of WPF program.


Let's check the DispatcherObject functionality with simple example. Open Microsoft Visual Studio => Create WPF Application and name it as "WPFDispatcherObject". Add Label & Button Control with Click event as shown below.


<Window x:Class="WPFDispatcherObject.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="MainWindow" Height="350" Width="525">

    <Grid>

        <Label Name="lbl1" Content="Label" Width="150" Height="50" Margin="0,0,0,100"></Label>

        <Button Name="btn" Content="Click" Click="btn_Click" Width="100" Height="50" Margin="10,10,10,10"  ></Button>

    </Grid>

</Window>

 

Change the Label content on button click event as shown below.


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;

using System.Threading;

 

namespace WPFDispatcherObject

{

    /// <summary>

    /// Interaction logic for MainWindow.xaml

    /// </summary>

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }

 

        private void btn_Click(object sender, RoutedEventArgs e)

        {

            Display();

        }

 

        private void Display()

        {

            lbl1.Content = "This is Label Control";

        }

    }

}

 

 

Run the application and click on button. The label content changed as we expected because this application is running on main thread only not on any other thread.


Now change the program as shown below.


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;

using System.Threading;

 

namespace WPFDispatcherObject

{

    /// <summary>

    /// Interaction logic for MainWindow.xaml

    /// </summary>

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }

 

        private void btn_Click(object sender, RoutedEventArgs e)

        {

            Thread thread = new Thread(Display);

            thread.Start();

        }

 

        private void Display()

        {

            lbl1.Content = "This is Label Control";

        }

    }

}

 

As shown above we are calling the Display() method on new thread in button click event. Run the application and click on the button. It throws error message as "The calling thread cannot access this object because a different thread owns it." as shown below.



If you want to call the Display() method on new thread change Display() method as shown below.


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;

using System.Threading;

using System.Windows.Threading;

 

namespace WPFDispatcherObject

{

    /// <summary>

    /// Interaction logic for MainWindow.xaml

    /// </summary>

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }

 

        private void btn_Click(object sender, RoutedEventArgs e)

        {

            Thread thread = new Thread(Display);

            thread.Start();

        }

 

        private void Display()

        {

            Dispatcher.Invoke(new Action(() => { lbl1.Content = "This is Label Control"; }));

        }

    }

}

 

In the above code within the Display() method we are using Dispatcher thread, that means we are using its own thread of Label control to change its content. So in this way we can use different threads to change the WPF controls content.

                                                                                                   WPFDispatcherObject.zip (50KB)

tags: