I my Blazor application I have such exception
System.InvalidOperationException: The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.
at Microsoft.AspNetCore.Components.Dispatcher.AssertAccess()
at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(Int32 componentId, RenderFragment renderFragment)
at Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()
at Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync(EventCallbackWorkItem callback, Object arg)
at Microsoft.AspNetCore.Components.EventCallback`1.InvokeAsync(TValue arg)
at MyApplication.Web.Shared.Application.ApplicationBarService.SearchFromUri(NavigationManager navigationManager) in /app/src/MyApplication.Web/Shared/Application/ApplicationBarService.cs:line 132
at MyApplication.Web.Shared.Application.ApplicationBar.OnAfterRenderAsync(Boolean firstRender) in /app/src/MyApplication.Web/Shared/Application/ApplicationBar.razor:line 367
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
2020-09-01 10:32:06.818 +00:00 [ERR] Unhandled exception in circuit 'b625BJVxR9Sa5e1W6l6unK0G7RAkkLuM3kbvMggpJV0'.
System.InvalidOperationException: The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.
at Microsoft.AspNetCore.Components.Dispatcher.AssertAccess()
at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(Int32 componentId, RenderFragment renderFragment)
at Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()
at Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync(EventCallbackWorkItem callback, Object arg)
at Microsoft.AspNetCore.Components.EventCallback`1.InvokeAsync(TValue arg)
at MyApplication.Web.Shared.Application.ApplicationBarService.SearchFromUri(NavigationManager navigationManager) in /app/src/MyApplication.Web/Shared/Application/ApplicationBarService.cs:line 132
at MyApplication.Web.Shared.Application.ApplicationBar.OnAfterRenderAsync(Boolean firstRender) in /app/src/MyApplication.Web/Shared/Application/ApplicationBar.razor:line 367
It asks to use InvokeAsync, but I'm already into an "OnAfterRenderAsync"! So, why do I have such an issue?
In my situation, I have 3 elements
- an ApplicationBarService (global to the app)
- an ApplicationBarComponent.razor
- a page Index.razor
What I suspect
The ApplicationBar component is inside the page Index.razor. It means that OnAfterRender is called on ApplicationBar first, then on Index.
So, here is the call stack / order:
- ApplicationBar.OnAfterRenderAsync ->
- ApplicationBarService.SearchFromUri -> (CALL DONE WITH AN EventCallback)
- Index.Search(...)
One problem is that Index.razor is not yet "ready" (no call to OnAfterRender has been done yet). There I cannot do any JS call :-(
Maybe I should do this call once all "parent" are ready, but how ?
Some code
It is a simple event
public EventCallback<SearchEventArgs> OnSearch;
I call it this way:
await OnSearch.InvokeAsync(args);
And the last code, On Index.razor I have:
public async Task Search(SearchArgs args)
{
base.InvokeAsync( ... );
}
The last method is the one called by the event, there I also use base.InvokeAsync to insure I do the call in the right thread ! But even with this I have some issues, I cannot do JS calls because the OnAfterRender has not been called yet !
So, do you have any idea about the problem?
Also, I have to some change, just to be sure to call from the same components. If you look at the code:
- I call from OnAfterRender, call a "static" class, then go back to the same component. Then this component try to do the last call.
- In the last call I use InvokeAsync and EventCallback (This one should InvokeAsync too)
But even with this, it ask me to call InvokeAsync (But it is done) !!!
