| File: DispatcherExtensions.cs | Web Access |
| Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls) |
using System; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Maui.Dispatching; using Microsoft.Maui.Hosting; namespace Microsoft.Maui.Controls { internal static class DispatcherExtensions { public static IDispatcher FindDispatcher(this BindableObject? bindableObject) { // try find the dispatcher in the current hierarchy // Exclude Application because we don't want to jump // directly to the Application IDispatcher at this point if (bindableObject is not Application && bindableObject is Element element && element.FindMauiContext() is IMauiContext context && context.Services.GetService<IDispatcher>() is IDispatcher handlerDispatcher) return handlerDispatcher; // maybe this thread has a dispatcher if (Dispatcher.GetForCurrentThread() is IDispatcher globalDispatcher) return globalDispatcher; // If BO is of type Application then return the Dispatcher from ApplicationDispatcher if (bindableObject is Application app && app.FindMauiContext() is IMauiContext appMauiContext) { if (appMauiContext.Services.GetOptionalApplicationDispatcher() is IDispatcher appDispatcherServiceDispatcher) return appDispatcherServiceDispatcher; // If BO is of type Application then check for its Dispatcher if (appMauiContext.Services.GetService<IDispatcher>() is IDispatcher appHandlerDispatcher) return appHandlerDispatcher; } // try looking on the static app // We don't include Application because Application.Dispatcher will call // `FindDispatcher` if it's _dispatcher property isn't initialized so this // could cause a Stack Overflow Exception if (bindableObject is not Application && Application.Current?.Dispatcher is IDispatcher appDispatcher) return appDispatcher; // no dispatchers found at all throw new InvalidOperationException("BindableObject was not instantiated on a thread with a dispatcher nor does the current application have a dispatcher."); } public static void DispatchIfRequired(this IDispatcher? dispatcher, Action action) { dispatcher = EnsureDispatcher(dispatcher); if (dispatcher.IsDispatchRequired) { dispatcher.Dispatch(action); } else { action(); } } public static Task DispatchIfRequiredAsync(this IDispatcher? dispatcher, Action action) { dispatcher = EnsureDispatcher(dispatcher); if (dispatcher.IsDispatchRequired) { return dispatcher.DispatchAsync(action); } else { action(); return Task.CompletedTask; } } public static Task DispatchIfRequiredAsync(this IDispatcher? dispatcher, Func<Task> action) { dispatcher = EnsureDispatcher(dispatcher); if (dispatcher.IsDispatchRequired) { return dispatcher.DispatchAsync(action); } else { return action(); } } static IDispatcher EnsureDispatcher(IDispatcher? dispatcher) { if (dispatcher is not null) return dispatcher; // maybe this thread has a dispatcher if (Dispatcher.GetForCurrentThread() is IDispatcher globalDispatcher) return globalDispatcher; // try looking on the app if (Application.Current?.Dispatcher is IDispatcher appDispatcher) return appDispatcher; // no dispatchers found at all throw new InvalidOperationException("The dispatcher was not found and the current application does not have a dispatcher."); } } }