2

I am writing an ASP.Net Core 3.1 application with bazor pages.

I want to fire a (slow) server-side calculation with the user clicks on a button.

What i want is to put a "loading..." message during calculation and then, display the message.

Here is what i've done in my C# Service class:

    public async Task<String> traitement1(String argument)
    {
        Thread.Sleep(5);  // I want to simulate a very slow calculation
        return await Task.FromResult("Finished ! Here is your result...");
    }

And here is what i've done in my bazor page:

<p>@my_result</p>

<button @onclick="@on_btn_click">Click me</button>

@code 
{
    private String my_result = "";

    private async void on_btn_click()
    {
        my_result = "Loading...";
        my_result = await mon_service.traitement1("aaa");
    }
}

It does not work... Any idea ?

Thanks

Bob5421
  • 7,757
  • 14
  • 81
  • 175
  • Does this answer your question? [Blazor - Display wait or spinner on API call](https://stackoverflow.com/questions/56604886/blazor-display-wait-or-spinner-on-api-call) – dani herrera Jun 16 '20 at 06:31
  • I hope you realise that `Thread.Sleep(5)` will delay the code for 5 milliseconds? Not enough time for the browser to register a change of state and re-render. Also, you should almost **never** use `async void`. And don't use `Thread.Sleep` - for Task-based async methods use `Task.Delay(5000)` for a 5-second delay – Quango Oct 22 '21 at 13:12

2 Answers2

2

First of all, avoid async void. Blazor fully supports async Task event handlers:

private async Task on_btn_click()
{
    my_result = "Loading...";
    await Task.Delay(1);   // give the Renderer a chance to catch up
    my_result = await mon_service.traitement1("aaa");
}

You need to insert the Task.Delay(1); because your traitement1() is not really async, it never gives up the Thread it runs on. Task.Yield() would have been clearer but it does not always work.

There is no need to call StateHasChanged() here.

H H
  • 263,252
  • 30
  • 330
  • 514
  • Could you elaborate on the last point? Why not call StateHasChanged()? – Chris Jensen Aug 23 '21 at 11:15
  • 1
    @ChrisJensen - Because Blazor already puts a StateHasChanged() before and after the event. The before one is consumed in Delay(1) and show "Loading.." , the after one shows the results. – H H Aug 23 '21 at 13:15
  • In other words, you can only omit the StateHasChanged call the first time if you have multiple updates triggered by the same event, correct? – Chris Jensen Aug 23 '21 at 13:29
  • 1
    No, you can always omit it unless you need > 2 screen updates. – H H Aug 23 '21 at 14:21
1

I have a component that can use. I just updated it to where you can either do the percentage complete yourself for a process, or you can set it to just increment on a periodic basis if you know about how long your process takes.

Nuget if you don't want to copy the code: DataJuggler.Blazor.Components

If you don't use the Nuget, you will need circle.scss:

(download from my GitHub) https://github.com/DataJuggler/DataJuggler.Blazor.Components/blob/master/wwwroot/css/circle.scss

Author who deserves credit is:

Andre Firchow

http://circle.firchow.net/

Either way, you will need to add it to your _host.cshtml file:

Nuget package way is shown here:

<link href="~/_content/DataJuggler.Blazor.Components/css/circle.css" rel="stylesheet" />

Or if the circle.scss is in your project file

<link href="~/css/circle.css" rel="stylesheet" />

I tried to post ProgressBar.razor and Progress.razor.cs code, but stack overflow told me I went over your 30,000 character limit, which I find hard to believe as little code as it is, so here is the link:

https://github.com/DataJuggler/DataJuggler.Blazor.Components/blob/master/ProgressBar.razor

https://github.com/DataJuggler/DataJuggler.Blazor.Components/blob/master/ProgressBar.razor.cs

Usage:

<div class="progresscontainer3">
    <ProgressBar Subscriber=this Increment="0" Interval="125" 
    ClientHandledIncrement="true" 
    CloseAtExtraPercent="0" Visible="@ShowProgress" Theme=ThemeEnum.Dark 
    Color=ColorEnum.Orange
    Size=SizeEnum.Small OverrideThemeColorForText="true" TextColor="White">
    </ProgressBar>
</div>

If you want to see a working example, Sign Up or upload an image, type in this query:

https://pixeldatabase.net

Hide
Total < 40

and click Apply.

Or there is a video here that also shows the progress bar:

https://youtu.be/K-reLOc1-Uo

I think it works pretty well.