Create a thread on the .NET MAUI UI thread

Browse sample. Browse the sample

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.