Create a thread on the .NET MAUI UI thread
This article describes how you can use the .NET Multi-platform App UI (.NET MAUI) MainThread class to run code on the main UI thread. Most operating systems use a single-threading model for code involving the user interface. This model is necessary to properly serialize user-interface events, including keystrokes and touch input. This thread is often called the main thread, the user-interface thread, or the UI thread. The disadvantage of this model is that all code that accesses user interface elements must run on the application's main thread.
The MainThread
class is available in the Microsoft.Maui.ApplicationModel
namespace.
When is it required
Applications sometimes need to use events that call the event handler on a secondary thread, such as the Accelerometer
or Compass
sensors. All sensors might return information on a secondary thread when used with faster sensing speeds. If the event handler needs to access user-interface elements, it must invoke code on the main thread.
Run code on the UI thread
To run code on the main thread, call the static MainThread.BeginInvokeOnMainThread method. The argument is an Action object, which is simply a method with no arguments and no return value:
MainThread.BeginInvokeOnMainThread(() =>
{
// Code to run on the main thread
});
It is also possible to define a separate method for the code, and then call that code with the BeginInvokeOnMainThread
method:
void MyMainThreadCode()
{
// Code to run on the main thread
}
MainThread.BeginInvokeOnMainThread(MyMainThreadCode);
Determine if invocation is required
With the MainThread class, you can determine if the current code is running on the main thread. The MainThread.IsMainThread property returns true
if the code calling the property is running on the main thread, and false
if it isn't. It's logical to assume that you need to determine if the code is running on the main thread before calling MainThread.BeginInvokeOnMainThread. For example, the following code uses the IsMainThread
to detect if the MyMainThreadCode
method should be called directly if the code is running on the main thread. If it isn't running on the main thread, the method is passed to BeginInvokeOnMainThread
:
if (MainThread.IsMainThread)
MyMainThreadCode();
else
MainThread.BeginInvokeOnMainThread(MyMainThreadCode);
This check isn't necessary. BeginInvokeOnMainThread
itself tests if the current code is running on the main thread or not. If the code is running on the main thread, BeginInvokeOnMainThread
just calls the provided method directly. If the code is running on a secondary thread, BeginInvokeOnMainThread
invokes the provided method on the main thread. Therefore, if the code you run is the same, regardless of the main or secondary thread, simply call BeginInvokeOnMainThread
without checking if it's required. There is negligible overhead in doing so.
The only reason you would need to check the IsMainThread
property is if you have branching logic that does something different based on the thread.
Additional methods
The MainThread class includes the following additional static
methods that can be used to interact with user interface elements from backgrounds threads:
Method | Arguments | Returns | Purpose |
---|---|---|---|
InvokeOnMainThreadAsync<T> |
Func<T> |
Task<T> |
Invokes a Func<T> on the main thread, and waits for it to complete. |
InvokeOnMainThreadAsync |
Action |
Task |
Invokes an Action on the main thread, and waits for it to complete. |
InvokeOnMainThreadAsync<T> |
Func<Task<T>> |
Task<T> |
Invokes a Func<Task<T>> on the main thread, and waits for it to complete. |
InvokeOnMainThreadAsync |
Func<Task> |
Task |
Invokes a Func<Task> on the main thread, and waits for it to complete. |
GetMainThreadSynchronizationContextAsync |
Task<SynchronizationContext> |
Returns the SynchronizationContext for the main thread. |