{"record":{"id":"a1758347a51b5ba0","repo":"dotnet/aspnetcore","slug":"the-current-thread-is-not-associated-with-the-disp","errorCode":null,"errorMessage":"The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.","messagePattern":"The current thread is not associated with the Dispatcher\\. Use InvokeAsync\\(\\) to switch execution to the Dispatcher when triggering rendering or component state\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/Dispatcher.cs","lineNumber":32,"sourceCode":"    /// <summary>\n    /// Creates a default instance of <see cref=\"Dispatcher\"/>.\n    /// </summary>\n    /// <returns>A <see cref=\"Dispatcher\"/> instance.</returns>\n    public static Dispatcher CreateDefault() => new RendererSynchronizationContextDispatcher();\n\n    /// <summary>\n    /// Provides notifications of unhandled exceptions that occur within the dispatcher.\n    /// </summary>\n    internal event UnhandledExceptionEventHandler? UnhandledException;\n\n    /// <summary>\n    /// Validates that the currently executing code is running inside the dispatcher.\n    /// </summary>\n    public void AssertAccess()\n    {\n        if (!CheckAccess())\n        {\n            throw new InvalidOperationException(\n                \"The current thread is not associated with the Dispatcher. \" +\n                \"Use InvokeAsync() to switch execution to the Dispatcher when \" +\n                \"triggering rendering or component state.\");\n        }\n    }\n\n    /// <summary>\n    /// Returns a value that determines whether using the dispatcher to invoke a work item is required\n    /// from the current context.\n    /// </summary>\n    /// <returns><c>true</c> if invoking is required, otherwise <c>false</c>.</returns>\n    public abstract bool CheckAccess();\n\n    /// <summary>\n    /// Invokes the given <see cref=\"Action\"/> in the context of the associated <see cref=\"Renderer\"/>.\n    /// </summary>\n    /// <param name=\"workItem\">The action to execute.</param>\n    /// <returns>A <see cref=\"Task\"/> that will be completed when the action has finished executing.</returns>","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/Dispatcher.cs#L14-L50","documentation":"Thrown by Dispatcher.AssertAccess when the calling thread is not the one associated with the Blazor synchronization context (the Dispatcher). Blazor component state and rendering must only be touched from the dispatcher's thread; calling rendering APIs or mutating component state from a background thread or external callback triggers this InvalidOperationException. The fix is to marshal the work back via InvokeAsync.","triggerScenarios":"Calling StateHasChanged(), component property setters, or CascadingValueSource methods from a Task continuation, a Timer.Elapsed handler, an event handler in a non-Blazor context, or any thread that isn't the dispatcher thread. AssertAccess is called at Dispatcher.cs:28-37.","commonSituations":"Using System.Timers.Timer instead of a dispatcher-aware timer; awaiting a long task and then touching state without InvokeAsync; subscribing to a non-Blazor event (e.g., a static event or message bus) and modifying component state in the handler.","solutions":["Wrap the state-mutating/rendering code in await InvokeAsync(() => { ... }).","Use a dispatcher-aware timer or post the callback through InvokeAsync.","For event handlers from external sources, capture the Dispatcher reference and always InvokeAsync through it."],"exampleFix":"// before\nprivate async Task LoadAsync()\n{\n    _data = await httpClient.GetFromJsonAsync<Data>(\"/api\");\n    StateHasChanged(); // may throw if off-dispatcher\n}\n\n// after\nprivate async Task LoadAsync()\n{\n    _data = await httpClient.GetFromJsonAsync<Data>(\"/api\");\n    await InvokeAsync(StateHasChanged);\n}","handlingStrategy":"validation","validationCode":"if (!Dispatcher.CheckAccess())\n    throw new InvalidOperationException(\"Not on dispatcher thread; use InvokeAsync.\");\n// or simply:\nawait Dispatcher.InvokeAsync(() => { /* work */ });","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always wrap post-await state mutations in InvokeAsync.","Use ComponentBase timers or dispatch Timer callbacks through InvokeAsync.","Never call StateHasChanged directly from a background thread."],"tags":["blazor","threading","dispatcher","concurrency"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}