Many SO answers use await Task.Delay(1)
to solve various async rendering issues in Blazor (wasm). I've even found a number of places in my own code where doing that "makes it work".
However it's always stated as matter of fact, without a thorough explanation, and I can't find this technique in the docs either.
Some questions:
- Why use
await Task.Delay(1)
- when would I use this technique, what is the use case? - The docs do not discuss this (that I could find); is it because it's a hack, or is it a legitimate way to deal with the use case?
- Any difference between
Task.Delay(1)
andTask.Yield()
?
CodePudding user response:
- Why use await Task.Delay(1)
To show intermediate results in an eventhandler.
- The docs do not discuss this
It is usually not needed. There's no argument against using it either.
I figured out how to use it when solving a problem like this. And I got some negative feedback, it does indeed look like a bit of a hack.
I suppose it could be solved with a Task StateHasChangedAsync()
method, that would just do a Task.Delay() internally. You can write it yourself:
public Task StateHasChangedAsync()
{
StateHasChanged(); // request a Render
return Task.Delay(1); // allow it to execute
}
- Any difference between Task.Delay(1) and Task.Yield()?
Yes, Task.Yield() looks more sensible but I found it does not always work.
The core point is that you only have one UI thread. That has to execute your events and the rendering process.
Blazor makes heavy use of async. Any time you release the UI thread with an await
Blazor will check if there are pending render requests (from StatehasChanged).
Sometimes that is unwelcome:
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
...
}
protected override async Task OnInitializedAsync()
{
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
}
Why does the FetchData page have a null check? Because the first Render will happen during the await
in OnInitializedAsync(), when forecasts is still null. And then a second Render will happen after the method is completed.
But in other cases, when you want a render to happen, don't rely on an await call being really async and guarantee it with a Task.Delay(1)
.
CodePudding user response:
Below is a link to a question answered by me and by Henk Holterman
, in whose answer he uses await Task.Delay(1);
Run the code, and see the difference, as for instance, using await Task.Delay(1);
results in re-rendering the component twice, etc.
Is the use of await Task.Delay(1);
necessary?
Absolutely not. This is a bad practice that not only results in a second re-rendering of a component, but it may lead to subtle issues with complex code. Blazor offers a list of life-cycle methods which you can capture and use to provide the wanted solutions. No hacking, please. This may prove very expensive in the long run. Create elegant code, not hacking...