File: MainThread\MainThread.shared.cs
Web Access
Project: src\src\Essentials\src\Essentials.csproj (Microsoft.Maui.Essentials)
using System;
using System.Threading;
using System.Threading.Tasks;
 
namespace Microsoft.Maui.ApplicationModel
{
	/// <summary>
	/// The MainThread class allows applications to run code on the main thread of execution, and to determine if a particular block of code is currently running on the main thread.
	/// </summary>
	public static partial class MainThread
	{
		/// <summary>
		/// True if the current thread is the UI thread.
		/// </summary>
		public static bool IsMainThread =>
			PlatformIsMainThread;
 
		/// <summary>
		/// Invokes an action on the main thread of the application.
		/// </summary>
		/// <param name="action">The action to invoke on the main thread.</param>
		public static void BeginInvokeOnMainThread(Action action)
		{
			if (IsMainThread)
			{
				action();
			}
			else
			{
				PlatformBeginInvokeOnMainThread(action);
			}
		}
 
		/// <summary>
		/// Invokes an action on the main thread of the application asynchronously.
		/// </summary>
		/// <param name="action">The action to invoke on the main thread.</param>
		/// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns>
		public static Task InvokeOnMainThreadAsync(Action action)
		{
			if (IsMainThread)
			{
				action();
				return Task.CompletedTask;
			}
 
			var tcs = new TaskCompletionSource<bool>();
 
			BeginInvokeOnMainThread(() =>
			{
				try
				{
					action();
					tcs.TrySetResult(true);
				}
				catch (Exception ex)
				{
					tcs.TrySetException(ex);
				}
			});
 
			return tcs.Task;
		}
 
		/// <summary>
		/// Invokes a function on the main thread of the application asynchronously.
		/// </summary>
		/// <typeparam name="T">Type of the object to be returned.</typeparam>
		/// <param name="func">The function task to execute on the main thread.</param>
		/// <returns>A <see cref="Task"/> object that can be awaited to capture the result object.</returns>
		public static Task<T> InvokeOnMainThreadAsync<T>(Func<T> func)
		{
			if (IsMainThread)
			{
				return Task.FromResult(func());
			}
 
			var tcs = new TaskCompletionSource<T>();
 
			BeginInvokeOnMainThread(() =>
			{
				try
				{
					var result = func();
					tcs.TrySetResult(result);
				}
				catch (Exception ex)
				{
					tcs.TrySetException(ex);
				}
			});
 
			return tcs.Task;
		}
 
		/// <summary>
		/// Invokes a function on the main thread of the application asynchronously.
		/// </summary>
		/// <param name="funcTask">The function task to execute on the main thread.</param>
		/// <returns>A <see cref="Task"/> object that can be awaited.</returns>
		public static Task InvokeOnMainThreadAsync(Func<Task> funcTask)
		{
			if (IsMainThread)
			{
				return funcTask();
			}
 
			var tcs = new TaskCompletionSource<object>();
 
			BeginInvokeOnMainThread(
				async () =>
				{
					try
					{
						await funcTask().ConfigureAwait(false);
						tcs.SetResult(null);
					}
					catch (Exception e)
					{
						tcs.SetException(e);
					}
				});
 
			return tcs.Task;
		}
 
		/// <summary>
		/// Invokes a function on the main thread of the application asynchronously.
		/// </summary>
		/// <typeparam name="T">Type of the object to be returned.</typeparam>
		/// <param name="funcTask">The function task to execute on the main thread.</param>
		/// <returns>A <see cref="Task"/> object that can be awaited to capture the result object.</returns>
		public static Task<T> InvokeOnMainThreadAsync<T>(Func<Task<T>> funcTask)
		{
			if (IsMainThread)
			{
				return funcTask();
			}
 
			var tcs = new TaskCompletionSource<T>();
 
			BeginInvokeOnMainThread(
				async () =>
				{
					try
					{
						var ret = await funcTask().ConfigureAwait(false);
						tcs.SetResult(ret);
					}
					catch (Exception e)
					{
						tcs.SetException(e);
					}
				});
 
			return tcs.Task;
		}
 
		/// <summary>
		/// Gets the main thread synchonization context.
		/// </summary>
		/// <returns>The synchronization context for the main thread.</returns>
		public static async Task<SynchronizationContext> GetMainThreadSynchronizationContextAsync()
		{
			SynchronizationContext ret = null;
			await InvokeOnMainThreadAsync(() =>
				ret = SynchronizationContext.Current).ConfigureAwait(false);
			return ret;
		}
	}
}