Option 1: Using Task.Delay(1)
- Use an async method.
- Use
await Task.Delay(1)
or await Task.Yield();
to flush changes
private async Task AsyncLongFunc() // this is an async task
{
spinning=true;
await Task.Delay(1); // flushing changes. The trick!!
LongFunc(); // non-async code
currentCount++;
spinning=false;
await Task.Delay(1); // changes are flushed again
}
Option 1 is a simple solution that runs ok but looks like a trick.
Option 2: Using Task.Run() (not for WebAssembly)
On January'2020. @Ed Charbeneau published BlazorPro.Spinkit project enclosing long processes into task to don't block the thread:
Ensure your LongOperation()
is a Task
, if it is not, enclose it into a Task
and await for it:
async Task AsyncLongOperation() // this is an async task
{
spinning=true;
await Task.Run(()=> LongOperation()); //<--here!
currentCount++;
spinning=false;
}
Effect
Spinner and server side prerendering
Because Blazor Server apps use pre-rendering the spinner will not appear, to show the spinner the long operation must be done in OnAfterRender.
Use OnAfterRenderAsync over OnInitializeAsync to avoid a delayed server-side rendering
// Don't do this
//protected override async Task OnInitializedAsync()
//{
// await LongOperation();
//}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await Task.Run(()=> LongOperation());//<--or Task.Delay(0) without Task.Run
StateHasChanged();
}
}
More samples
Learn more about how to write nice spinner you can learn from open source project BlazorPro.Spinkit, it contains clever samples.
More Info
See Henk Holterman's answer with blazor internals explanation.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…