Reputation: 1327
Our Blazor (client-side) app is made up of many components all existing on the UI at the same time. One of these has to do a number of large data calls to Azure SQL. This component does these calls regardless of whether it has UI focus or not. Each of calls these can take up to 3 seconds to return its result during which it renders the UI unresponsive. How can we keep the UI responsive during these calls without using Blazor server-side. Using Task.Run etc does not help in single threaded architecture. Using loading spinners is also not an option as this still leaves the UI unresponsive and may not be visible to the user. Is there any way to achieve this goal in current Blazor 0.9.0?
Running latest Blazor preview release (0.9.0-preview3-19154-02)
Upvotes: 7
Views: 5836
Reputation: 1179
the suggested answer did not work, for me, I ended up using :
protected override void OnInitialized()
{
InvokeAsync(async () =>
{
myvar = await YourCodeHere();
StateHasChanged();
});
base.OnInitialized();
}
public async Task<MyVarType> YourCodeHere()
{
...
}
Explanation: I have a class called MyVarType that I am using to display values on the Razor component. I have a myVar variable instantiated with that class, and initially it is empty. The component will render its default values immediately. Upon initializing the variable is then also being asynchronously assigned from the OnInitialized method. The YourCodeHere function could take several seconds. The Razor component rerenders when calling StateHasChanged() so it displays the loaded values.
Upvotes: -1
Reputation: 305
I've had success with Task().Start()
put your work in an async Task like so:
async Task MyWork()
{
//sleep 10000
}
now from wherever you don't want this work to block call:
new Task( () => MyWork()).Start() );
I've only used this with Blazor Server, so haven't tested it with Client side Blazor which I hear can have different results because of its running on a single thread.
Upvotes: 0
Reputation: 51655
You can use Invoke
, I modified counter
example page to illustrate it, you will need a kind of singleton DI object to avoid running the process for twice.
Remember Blazor
is an experimental project. Also, this answer is also an experimental approach.
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>
@functions {
int currentCount = 0;
void IncrementCount()
{
currentCount++;
}
protected override void OnInit()
{
Invoke(
//here your task.
async () =>
{
for(var i =0; i< 50; i++)
{
await Task.Delay(1000);
currentCount++;
StateHasChanged();
System.Console.WriteLine("Still running ...");
}
});
}
}
Upvotes: 2
Reputation: 112
If async calls does not help then you can use browser workers, just need to implement some js interop.
Upvotes: 1