C# Controls Examples
C# Basic
C# Data Type
C# OOP
C# IO
C# Graphics & UI
C# Advanced
In C#, updating the GUI from another thread is not allowed, as it can cause unpredictable behavior. To update the GUI from another thread, you can use the Invoke
or BeginInvoke
methods provided by the Control
class in WinForms or the Dispatcher.Invoke
or Dispatcher.BeginInvoke
methods in WPF.
Here's how to update the GUI from another thread in WinForms and WPF:
WinForms:
Create a new C# Windows Forms Application using Visual Studio or any other C# development environment. Name it WinFormsThreadUpdate
.
Add a Label and a Button control to the form by dragging them from the Toolbox onto the form. Set the Name
property of the Label to labelResult
and the Button to btnUpdate
.
Double-click the button on the form to generate a click event handler in the Form1.cs
file.
Add the following code to the Click event handler:
private void btnUpdate_Click(object sender, EventArgs e) { Task.Run(() => { string text = "Updated from another thread"; this.Invoke((MethodInvoker)delegate { labelResult.Text = text; }); }); }
This code starts a new task that runs on another thread and attempts to update the labelResult.Text
property. To safely update the GUI from the non-UI thread, the Invoke
method is used with a MethodInvoker
delegate.
WPF:
Create a new C# WPF Application using Visual Studio or any other C# development environment. Name it WPFThreadUpdate
.
Open the MainWindow.xaml
file and add a Label and a Button control inside the Grid:
<Grid> <StackPanel> <Button x:Name="btnUpdate" Content="Update Label" Click="BtnUpdate_Click" /> <Label x:Name="labelResult" Content="Initial Text" /> </StackPanel> </Grid>
Add the following code to the MainWindow.xaml.cs
file to handle the Button click event:
private void BtnUpdate_Click(object sender, RoutedEventArgs e) { Task.Run(() => { string text = "Updated from another thread"; this.Dispatcher.Invoke(() => { labelResult.Content = text; }); }); }
This code starts a new task that runs on another thread and attempts to update the labelResult.Content
property. To safely update the GUI from the non-UI thread, the Dispatcher.Invoke
method is used.
Now, when you run either the WinForms or WPF application and click the button, the label will be updated with the text "Updated from another thread". The GUI update is performed safely from another thread using the Invoke
method in WinForms or the Dispatcher.Invoke
method in WPF.
C# update GUI from another thread:
Control.Invoke
, or Dispatcher.Invoke
to update UI from a different thread.private void UpdateUI(string text) { if (label1.InvokeRequired) { label1.Invoke(new Action(() => label1.Text = text)); } else { label1.Text = text; } }
Cross-thread operation not valid in C#:
// Causes cross-thread operation exception label1.Text = "Updated from another thread!";
Invoke vs BeginInvoke in C#:
Invoke
is synchronous, blocking until the operation completes. BeginInvoke
is asynchronous.label1.Invoke(new Action(() => label1.Text = "Invoke")); label1.BeginInvoke(new Action(() => label1.Text = "BeginInvoke"));
Updating UI asynchronously in C#:
Task.Run
or async/await
for asynchronous UI updates.await Task.Run(() => { // UI update logic UpdateUI("Async update"); });
Thread-safe UI updates in C#:
lock
or Monitor
to ensure thread safety.private readonly object lockObject = new object(); private void UpdateUI(string text) { lock (lockObject) { label1.Text = text; } }
Dispatcher in C# for WPF:
Dispatcher
for thread-safe UI updates in WPF.Dispatcher.Invoke(() => label1.Content = "Updated from another thread!");
Control.InvokeRequired in WinForms:
InvokeRequired
property before updating UI in WinForms.private void UpdateUI(string text) { if (label1.InvokeRequired) { label1.Invoke(new Action(() => label1.Text = text)); } else { label1.Text = text; } }
SynchronizationContext in C#:
SynchronizationContext
for context-aware thread-safe updates.SynchronizationContext.Current.Post(_ => UpdateUI("Thread-safe update"), null);
Async and await for UI updates in C#:
async/await
for asynchronous UI updates without blocking.private async void UpdateUIAsync(string text) { await Task.Run(() => UpdateUI(text)); }
Updating WinForms UI from another thread:
Control.Invoke
or BeginInvoke
for thread-safe updates in WinForms.private void UpdateUI(string text) { if (label1.InvokeRequired) { label1.Invoke(new Action(() => label1.Text = text)); } else { label1.Text = text; } }
BackgroundWorker in WinForms for UI updates:
BackgroundWorker
for simple background tasks with UI updates.private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { // Background work } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // UI update UpdateUI("Completed!"); }
Control.Invoke and Control.BeginInvoke in WinForms:
private void UpdateUI(string text) { if (label1.InvokeRequired) { label1.Invoke(new Action(() => label1.Text = text)); } else { label1.Text = text; } }
Asynchronous UI updates in WinForms:
async/await
for asynchronous UI updates without blocking.private async void UpdateUIAsync(string text) { await Task.Run(() => UpdateUI(text)); }
Using BackgroundWorker for safe UI updates in C#:
BackgroundWorker
simplifies background tasks with UI updates.private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { // Background work } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // UI update UpdateUI("Completed!"); }
Updating WPF UI from another thread:
Dispatcher.Invoke
or Dispatcher.BeginInvoke
for thread-safe updates in WPF.Dispatcher.Invoke(() => label1.Content = "Updated from another thread!");
Dispatcher.Invoke and Dispatcher.BeginInvoke in WPF:
Dispatcher.Invoke(() => label1.Content = "Updated from another thread!");
Asynchronous UI updates in WPF:
async/await
for asynchronous UI updates without blocking.private async void UpdateUIAsync(string text) { await Task.Run(() => UpdateUI(text)); }
Using async/await in WPF for UI updates:
async/await
for asynchronous UI updates without blocking.private async void UpdateUIAsync(string text) { await Task.Run(() => UpdateUI(text)); }
ObservableCollection for thread-safe data binding in WPF:
ObservableCollection
for automatic thread-safe data binding.private ObservableCollection<string> items = new ObservableCollection<string>(); public MainWindow() { InitializeComponent(); listBox.ItemsSource = items; } private void UpdateItems(string item) { items.Add(item); }