Перейти к основному содержимому
Версия: 11.0.0

How To Access the UI Thread

This guide will show you how to access the UI thread in your Avalonia UI application.

Avalonia UI applications have one main thread, and this handles the UI. When you have a process that is intensive, or long running, then you will usually opt to run it on a different thread. Then you may have scenarios where you want to update them main UI thread (for example with progress updates).

A dispatcher provides services for managing work items on any specific thread. In Avalonia UI you will already have the dispatcher that handles the UI thread. When you need to update the UI from a different thread, you access it through this dispatcher, as follows:

Dispatcher.UIThread

You can use either the Post method or the InvokeAsync method to run a process on the UI thread.

Use Post when you just want to start a job, but you do not need to wait for the job to be finished, and you do not need the result: this is the 'fire-and-forget' dispatcher method.

Use InvokeAsync when you need to wait for the result, and potentially want to receive the result.

Dispatcher Priority

Both of the above methods have a dispatcher priority parameter. You can use this with the DispatcherPriority enumeration to specify the queue priority that the given job should be given.

к сведению

For the possible values of the DispatcherPriority enumeration, see here.

Example

In this example a text block is used to show the result of a long running task, and a button is used to start the work. In this version, the fire-and-forget Post method is used:

XAML
<StackPanel Margin="20">    
<Button x:Name="RunButton" Content="Run long running process"
Click="ButtonClickHandler" />
<TextBlock x:Name="ResultText" Margin="10"/>
</StackPanel>
Task C#
using System.Threading.Tasks;
...
private async Task LongRunningTask()
{
this.FindControl<Button>("RunButton").IsEnabled = false;
this.FindControl<TextBlock>("ResultText").Text = "I'm working ...";
await Task.Delay(5000);
this.FindControl<TextBlock>("ResultText").Text = "Done";
this.FindControl<Button>("RunButton").IsEnabled = true;
}
Post C#
private void ButtonClickHandler(object sender, RoutedEventArgs e)
{
// Start the job and return immediately
Dispatcher.UIThread.Post(() => LongRunningTask(),
DispatcherPriority.Background);
}

Notice that because the long running task is executed on its own thread, the UI does not lose responsiveness.

To get a result from the long running task, the XAML is the same, but this version uses the InvokeAsyncmethod:

XAML
<StackPanel Margin="20">    
<Button x:Name="RunButton" Content="Run long running process"
Click="ButtonClickHandler" />
<TextBlock x:Name="ResultText" Margin="10" />
Task C#
using System.Threading.Tasks;
...
private async Task<string> LongRunningTask()
{
this.FindControl<Button>("RunButton").IsEnabled = false;
this.FindControl<TextBlock>("ResultText").Text = "I'm working ...";
await Task.Delay(5000);
return "Success";
}
InvokeAsync C#
private async void ButtonClickHandler(object sender, RoutedEventArgs e)
{
var result = await Dispatcher.UIThread.InvokeAsync(LongRunningTask,
DispatcherPriority.Background);
//result returns here
this.FindControl<TextBlock>("ResultText").Text = result;
this.FindControl<Button>("RunButton").IsEnabled = true;
}

More Information

к сведению

For the complete API documentation about the dispatcher, see here.

к сведению

View the source code on GitHub Dispatcher.cs