Edit: for clarification, this is in a Blazor Server application
I'm confused about the correct usage of InvokeAsync and updating the UI. The documentation has several usages without really explaining the reason for awaiting or not awaiting. I have also seen some contradictory threads without much to backup their reasoning.
It seems wrong to make all methods async to await InvokeAsync(StateHasChanged) and I read somewhere that the reason InvokeAsync was introduced was to prevent the need for async code everywhere. But then what situations might I want to await it?
awaiting:
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-5.0&viewFallbackFrom=aspnetcore-3.0#invoke-component-methods-externally-to-update-state
non-await discard:
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/rendering?view=aspnetcore-5.0
Here are some examples of different usages that I have seen, if anyone could explain or share any links with information on some of the differences between them that'd be great (thanks!)
public void IncrementCounter()
{
_counter++;
InvokeAsync(StateHasChanged);
}
public void IncrementCounter()
{
InvokeAsync(() =>
{
_counter++;
StateHasChanged);
}
}
public async Task IncrementCounter()
{
_counter++;
await InvokeAsync(StateHasChanged);
}
public async Task IncrementCounter()
{
await InvokeAsync(() =>
{
_counter++;
StateHasChanged();
});
}
IncrementCounter (a ButtonClick handler) is the wrong thing to look at - it always runs on the SyncContext thread and can always use a plain StateHasChanged() without Invoke.
So lets look at a Timer event instead. The Threading.Timer class does not support async handlers so you run in a void Tick() { ... } on an unspecified thread.
You do need InvokeAsync(StateHasChanged) here. You could make the Tick method an async void just to await the InvokeAsync but that gives of the wrong signals. Using InvokeAsync without await is the lesser evil.
void Tick() // possibly threaded event handler
{
_counter++;
InvokeAsync(StateHasChanged); // fire-and-forget mode
}
But when you are in an async method and still need InvokeAsync, it is neater to await it, just because you can.
async Task SomeService()
{
_counter++;
await InvokeAsync(StateHasChanged);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With