| File: Dispatcher.cs | Web Access |
| Project: src\aspnetcore\src\Components\Components\src\Microsoft.AspNetCore.Components.csproj (Microsoft.AspNetCore.Components) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.Sections; namespace Microsoft.AspNetCore.Components; /// <summary> /// Dispatches external actions to be executed on the context of a <see cref="Renderer"/>. /// </summary> public abstract class Dispatcher { private SectionRegistry? _sectionRegistry; /// <summary> /// Creates a default instance of <see cref="Dispatcher"/>. /// </summary> /// <returns>A <see cref="Dispatcher"/> instance.</returns> public static Dispatcher CreateDefault() => new RendererSynchronizationContextDispatcher(); /// <summary> /// Provides notifications of unhandled exceptions that occur within the dispatcher. /// </summary> internal event UnhandledExceptionEventHandler? UnhandledException; /// <summary> /// Gets the <see cref="Sections.SectionRegistry"/> associated with the dispatcher. /// </summary> internal SectionRegistry SectionRegistry => _sectionRegistry ??= new(); /// <summary> /// Validates that the currently executing code is running inside the dispatcher. /// </summary> public void AssertAccess() { if (!CheckAccess()) { throw new InvalidOperationException( "The current thread is not associated with the Dispatcher. " + "Use InvokeAsync() to switch execution to the Dispatcher when " + "triggering rendering or component state."); } } /// <summary> /// Returns a value that determines whether using the dispatcher to invoke a work item is required /// from the current context. /// </summary> /// <returns><c>true</c> if invoking is required, otherwise <c>false</c>.</returns> public abstract bool CheckAccess(); /// <summary> /// Invokes the given <see cref="Action"/> in the context of the associated <see cref="Renderer"/>. /// </summary> /// <param name="workItem">The action to execute.</param> /// <returns>A <see cref="Task"/> that will be completed when the action has finished executing.</returns> public abstract Task InvokeAsync(Action workItem); /// <summary> /// Invokes the given <see cref="Func{TResult}"/> in the context of the associated <see cref="Renderer"/>. /// </summary> /// <param name="workItem">The asynchronous action to execute.</param> /// <returns>A <see cref="Task"/> that will be completed when the action has finished executing.</returns> public abstract Task InvokeAsync(Func<Task> workItem); /// <summary> /// Invokes the given <see cref="Func{TResult}"/> in the context of the associated <see cref="Renderer"/>. /// </summary> /// <param name="workItem">The function to execute.</param> /// <returns>A <see cref="Task{TResult}"/> that will be completed when the function has finished executing.</returns> public abstract Task<TResult> InvokeAsync<TResult>(Func<TResult> workItem); /// <summary> /// Invokes the given <see cref="Func{TResult}"/> in the context of the associated <see cref="Renderer"/>. /// </summary> /// <param name="workItem">The asynchronous function to execute.</param> /// <returns>A <see cref="Task{TResult}"/> that will be completed when the function has finished executing.</returns> public abstract Task<TResult> InvokeAsync<TResult>(Func<Task<TResult>> workItem); /// <summary> /// Called to notify listeners of an unhandled exception. /// </summary> /// <param name="e">The <see cref="UnhandledExceptionEventArgs"/>.</param> protected void OnUnhandledException(UnhandledExceptionEventArgs e) { ArgumentNullException.ThrowIfNull(e); UnhandledException?.Invoke(this, e); } }