跳到主要内容
版本:11.0.0

如何访问UI线程

本指南将向您展示如何在您的 Avalonia UI 应用程序中访问UI线程。

Avalonia UI 应用程序有一个主线程,该线程处理UI。当您有一个密集或长时间运行的进程时,通常会选择在不同的线程上运行它。然后,您可能会遇到一些情况,希望在主UI线程中进行更新(例如,进度更新)。

调度程序提供了在任何特定线程上管理工作项的服务。在 Avalonia UI 中,您已经有了处理UI线程的调度程序。当您需要从不同的线程更新UI时,可以通过此调度程序访问它,如下所示:

Dispatcher.UIThread

您可以使用Post方法或InvokeAsync方法在UI线程上运行进程。

使用Post方法当您只想启动一个作业,但不需要等待作业完成,也不需要结果:这是fire-and-forget调度程序方法。

使用InvokeAsync方法当您需要等待结果,并可能想要接收结果。

调度程序优先级

上述两种方法都有一个调度程序优先级参数。您可以使用DispatcherPriority枚举与此参数配合使用,以指定给定作业应该具有的队列优先级。

信息

有关DispatcherPriority枚举的可能值,请参阅此处

示例

此示例演示了如何从工作线程访问 UI 线程以更新或获取 TextBlock 的文本。 创建一个新的 Avalonia 项目,并替换以下两个文件的内容:

MainView.axaml:

XAML
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:AvaloniaApplication1.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloniaApplication1.Views.MainView"
x:DataType="vm:MainViewModel">
<Design.DataContext>
<!-- 这仅为IDE中的预览器设置DataContext,要设置运行时的实际DataContext,
请在代码中设置DataContext属性(参考App.axaml.cs) -->
<vm:MainViewModel />
</Design.DataContext>

<StackPanel Margin="20">
<TextBlock Name="TextBlock1" />
</StackPanel>
</UserControl>

MainView.axaml.cs:

MainView C#
using Avalonia.Controls;
using Avalonia.Threading;
using System;
using System.Threading.Tasks;

namespace AvaloniaApplication1.Views;

public partial class MainView : UserControl
{
public MainView()
{
InitializeComponent();

// 在线程池上执行 OnTextFromAnotherThread,
// 演示如何从那里访问 UI 线程。
_ = Task.Run(() => OnTextFromAnotherThread("test"));
}

private void SetText(string text) => TextBlock1.Text = text;
private string GetText() => TextBlock1.Text ?? "";

private async void OnTextFromAnotherThread(string text)
{
try
{
// 在 UI 线程上开始作业并立即返回。
Dispatcher.UIThread.Post(() => SetText(text));

// 在 UI 线程上开始作业并等待结果。
var result = await Dispatcher.UIThread.InvokeAsync(GetText);

// 此调用会导致异常,因为我们在工作线程上运行:
// System.InvalidOperationException: 'Call from invalid thread'
//SetText(text);
}
catch (Exception)
{
throw; // Todo: 处理异常。
}
}
}

更多信息

信息

有关调度程序的完整API文档,请参阅此处

信息

GitHub 上查看源代码 Dispatcher.cs