本文介绍如何使用 .NET 多平台应用 UI (.NET MAUI) MainThread 类在主 UI 线程上运行代码。 大多数作系统对涉及用户界面的代码使用单线程模型。 此模型是正确序列化用户界面事件(包括击键和触摸输入)所必需的。 此线程通常称为 主线程、 用户界面线程或 UI 线程。 此模型的缺点是访问用户界面元素的所有代码都必须在应用程序的主线程上运行。
MainThread 类可从 Microsoft.Maui.ApplicationModel 命名空间中获得。
何时需要
应用程序有时需要使用在辅助线程(如 Accelerometer 或 Compass 传感器)上调用事件处理程序的事件。 当与更快的感应速度一起使用时,所有传感器都可能会返回辅助线程上的信息。 如果事件处理程序需要访问用户界面元素,则必须在主线程上调用代码。
在 UI 线程上运行代码
若要在主线程上运行代码,请调用静态 MainThread.BeginInvokeOnMainThread 方法。 该参数是一个 Action 对象,它只是一个没有参数且没有返回值的方法:
MainThread.BeginInvokeOnMainThread(() =>
{
// Code to run on the main thread
});
还可以为代码定义单独的方法,然后使用该方法调用该代码 BeginInvokeOnMainThread :
void MyMainThreadCode()
{
// Code to run on the main thread
}
MainThread.BeginInvokeOnMainThread(MyMainThreadCode);
确定是否需要调用
MainThread使用类,可以确定当前代码是否在主线程上运行。 如果调用该属性的代码在主线程上运行,属性将返回MainThread.IsMainThread;如果代码不在主线程上运行,属性将返回false。 假设在调用 MainThread.BeginInvokeOnMainThread之前代码是否在主线程上运行,这是合乎逻辑的。 例如,下面的代码使用 IsMainThread 来检测如果代码在主线程上运行,是否应该直接调用 MyMainThreadCode 方法。 如果该方法不在主线程上运行,则会传递到BeginInvokeOnMainThread。
if (MainThread.IsMainThread)
MyMainThreadCode();
else
MainThread.BeginInvokeOnMainThread(MyMainThreadCode);
对于此方案,不需要进行此检查。
BeginInvokeOnMainThread 本身测试当前代码是否在主线程上运行。 如果代码在主线程上运行, BeginInvokeOnMainThread 只需直接调用提供的方法。 如果代码在辅助线程上运行,则 BeginInvokeOnMainThread 调用主线程上提供的方法。 因此,如果运行的代码是相同的,而不考虑主线程或辅助线程,只需调用 BeginInvokeOnMainThread 而不检查是否需要它。 这样做会产生微不足道的开销。
需要检查 IsMainThread 属性的唯一原因是,如果分支逻辑依据线程执行不同的操作。
其他方法
该 MainThread 类包括以下可用于与后台线程中的用户界面元素交互的其他 static 方法:
| 方法 | 论据 | 退货 | 目的 |
|---|---|---|---|
InvokeOnMainThreadAsync<T> |
Func<T> |
Task<T> |
在主线程上调用 a Func<T> ,并等待它完成。 |
InvokeOnMainThreadAsync |
Action |
Task |
在主线程上调用一个 Action ,并等待它完成。 |
InvokeOnMainThreadAsync<T> |
Func<Task<T>> |
Task<T> |
在主线程上调用 a Func<Task<T>> ,并等待它完成。 |
InvokeOnMainThreadAsync |
Func<Task> |
Task |
在主线程上调用 a Func<Task> ,并等待它完成。 |
GetMainThreadSynchronizationContextAsync |
Task<SynchronizationContext> |
返回主线程的SynchronizationContext。 |
浏览示例