Featured image of post C# Threading Techniques with WPF and WinForms

C# Threading Techniques with WPF and WinForms

Thread UI tricks with .Net and C#

Updating User Interfaces in WPF and WinForms with Threading Techniques

In user interface (UI) applications such as WPF (Windows Presentation Foundation) and WinForms, thread management is essential because UI elements can only be updated from the UI thread.

Any attempt to update the UI from a background thread will result in an exception.

When using threading techniques such as Thread, ThreadPool, Task, or async/await, it is important to marshal UI updates to the UI thread.

Below, we’ll explore how to update the UI in WPF and WinForms using different threading techniques.

WPF - Updating the UI

In WPF, the UI thread is the main thread that manages UI updates.

To update UI elements from a background thread, you need to use the Dispatcher to marshal the call back to the UI thread.

1. Using Thread

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public void StartBackgroundTask()
{
    Thread backgroundThread = new Thread(() =>
    {
        // Simulate long-running task
        Thread.Sleep(2000);

        // Update the UI from the UI thread using Dispatcher
        Dispatcher.Invoke(() =>
        {
            myLabel.Content = "Task Completed";  // Update UI element
        });
    });

    backgroundThread.Start();
}

2. Using ThreadPool

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public void StartBackgroundTask()
{
    ThreadPool.QueueUserWorkItem(state =>
    {
        // Simulate long-running task
        Thread.Sleep(2000);

        // Update the UI from the UI thread using Dispatcher
        Dispatcher.Invoke(() =>
        {
            myLabel.Content = "Task Completed";
        });
    });
}

3. Using Task (Task.Run)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public async Task StartBackgroundTaskAsync()
{
    await Task.Run(() =>
    {
        // Simulate long-running task
        Thread.Sleep(2000);
    });

    // Update the UI from the UI thread
    myLabel.Content = "Task Completed";
}

4. Using async/await

1
2
3
4
5
6
7
public async Task StartBackgroundTaskAsync()
{
    await Task.Delay(2000);  // Simulate an async I/O-bound task

    // This update happens on the UI thread automatically after awaiting
    myLabel.Content = "Task Completed";
}

WinForms - Updating the UI

In WinForms, similar to WPF, UI elements can only be updated from the main UI thread.

You can use the Invoke method to marshal the update from a background thread to the UI thread.

1. Using Thread

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public void StartBackgroundTask()
{
    Thread backgroundThread = new Thread(() =>
    {
        // Simulate long-running task
        Thread.Sleep(2000);

        // Update UI from the UI thread using Invoke
        myLabel.Invoke((Action)(() =>
        {
            myLabel.Text = "Task Completed";  // Update UI element
        }));
    });

    backgroundThread.Start();
}

2. Using ThreadPool

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public void StartBackgroundTask()
{
    ThreadPool.QueueUserWorkItem(state =>
    {
        // Simulate long-running task
        Thread.Sleep(2000);

        // Update UI from the UI thread using Invoke
        myLabel.Invoke((Action)(() =>
        {
            myLabel.Text = "Task Completed";
        }));
    });
}

3. Using Task (Task.Run)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public async Task StartBackgroundTaskAsync()
{
    await Task.Run(() =>
    {
        // Simulate long-running task
        Thread.Sleep(2000);
    });

    // Update UI from UI thread
    myLabel.Text = "Task Completed";
}

4. Using async/await

1
2
3
4
5
6
7
public async Task StartBackgroundTaskAsync()
{
    await Task.Delay(2000);  // Simulate an async I/O-bound task

    // This update happens on the UI thread after the await completes
    myLabel.Text = "Task Completed";
}