Introduction
Threading enables a program to do concurrent processing so that it can do more than one operation at a time. Window Presentation Foundation (WPF) has been designed such that it saves the developer from the difficulties of threading. This article can help you to understand the proper use of threading in WPF.
WPF Internal threads and rules
All WPF applications run with a minimum of the following two threads:
- For rendering: It runs in the background, so it is hidden.
- For managing UI interface (UI thread): Most of the WPF objects are tied with UI threads. It receives input, paints the screen, runs code and handles events.
WPF supports a single-threaded apartment model that has the following rules:
- One thread runs in the entire application and owns all the WPF objects.
- WPF elements have thread affinity, in other words other threads can't interact with each other.
- WPF objects that have thread affinity derive from the Dispatcher object.
Thread handling in WPF by developer
When creating an application in WPF the developer must sometimes manage the threads, so it provides some way to handle and use the thread in the application on various scenarios. The following are the two ways for handling the threads:
- The Dispatcher
- The Background Worker.
The Dispatcher
The Dispatcher is an instance of the System.Windows.Threading.Dispatcher class. It owns the application thread and manages a queue of work items. It executes UI operations in a First in First Out (FIFO) manner by taking priority of each. It does not create a new thread. It is not multi-threaded.
Every Visual WPF object derives from a DispatcherObject. It is an object that is linked to the DispatcherObject class. The following are the members of the DispatcherObject class:
- Properties
- Dispatcher: It gets a Dispatcher.
- Methods
There are several methods in the DispatcherObject Class. Some important methods are the following:
- CheckAccess(): It returns true if the code is a thread that can use the object.
- VerifyAccess(): Does nothing if the code is in the correct thread to use the object otherwise it throws an “InvalidOperationException”.
- GetType(): It gets the type of current instance.
WPF objects call VerifyAccess() frequently to project themselves.
Why do we need Dispatcher?
An example that will clarify the need of Dispatcher in WPF Application:
- using System;
-
- using System.Threading;
-
- using System.Windows;
-
- namespace WpfApplication1
- {
-
-
-
-
-
-
-
-
-
- public partial class MainWindow : Window
- {
-
- public MainWindow()
- {
-
- InitializeComponent();
-
- }
-
- private void MyButton_Click(object sender, RoutedEventArgs e)
- {
-
- Thread thread = new Thread(UpdateText);
-
- thread.Start();
-
-
- }
-
- private void UpdateText()
- {
-
- Thread.Sleep(TimeSpan.FromSeconds(5));
-
- TxtName.Text = "Hello Geeks !";
-
- }
-
- }
-
- }
Now, this is the wrong code because the UpdateText() method will be executed on a new thread and that thread is not allowed to access WPF objects.
Method “VerifyAccess()” is called and an “InvalidOperationException” is thrown.
The following is the correction of the code above:
- using System;
-
- using System.Threading;
-
- using System.Windows;
-
- namespace WpfApplication1
- {
-
-
-
-
-
-
-
-
-
- public partial class MainWindow : Window
- {
-
- public MainWindow()
- {
-
- InitializeComponent();
-
- }
-
- private void MyButton_Click(object sender, RoutedEventArgs e)
- {
-
- Thread thread = new Thread(UpdateText);
-
- thread.Start();
-
- ;
-
- }
-
- private void UpdateText()
- {
-
- Thread.Sleep(TimeSpan.FromSeconds(5));
-
- this.Dispatcher.BeginInvoke(new Action(() =>
- {
-
- TxtName.Text = "Hello Geeks !";
-
- }));
-
- }
-
- }
-
- }
So, Dispatcher is the best way for updating a WPF UI with a thread.
The Background WorkerIt is very beneficial in time-consuming tasks. It executes the code at the same time. It is invoked in a separate thread. It automatically synchronizes with the main thread of an application.
It is used to run an operation in the background and defers execution to the UI. The following are some cases where a Background worker can be used:
- If the user wants a responsive UI and faces delays in specific operations.
- Data download.
- Database transactions.
BackgroundWorker is a class under System.ComponentModel. It executes the operation on a separate thread.
Output:
Difference between Dispatcher and Background Worker
- Background worker executes the code at the same time it is invoked in a separate thread. It automatically synchronizes with the main thread of a WPF application when the Dispatcher processes a queue of things to do every time.
- A Background worker executes in a separate thread whereas the dispatcher runs with the UI thread of a WPF application.
- If you want to run an operation in the background of the UI, use a background worker but use the Dispatcher to marshal updates back to the WPF UI.