Home > Mobile >  Why is my Blazor Server App waiting to render until data has been retrieved, even when using async?
Why is my Blazor Server App waiting to render until data has been retrieved, even when using async?

Time:12-27

I'm building a Blazor Server app using .NET 6. As an example I have a list of customers that I retrieve from a Sqlite db using Entityframework Core. I want to show a loading indicator when the data is still being retrieved. Like so:

@page "/customers"
@inject CustomerService CustomerService


@if(customers.Count == 0)
{
    <p>Loading...</p>
}
else
{
    <table>
        @foreach(Customer customer in customers)
        {
            <tr>
                <td>
                    @customer.Id
                </td>
                <td>
                    @customer.Name
                </td>
            </tr>
        }
    </table>
}

When I use following data implementation it works fine:

private List<Customer> customers = new();

protected async override Task OnInitializedAsync()
{
    await Task.Run(() =>
    {
        this.customers = CustomerService.GetCustomers();
    });
}

However when I use following data implementation it doesn't work. Meaning that the entire page only becomes visible once the data has been loaded (white page while waiting).

private List<Customer> customers = new();

protected async override Task OnInitializedAsync()
{
    this.customers = await CustomerService.GetCustomersAsync();
}

CustomerService.cs

    public class CustomerService
    {
        private CustomerContext _customerContext;

        public CustomerService(CustomerContext customerContext)
        {
            _customerContext = customerContext;
        }

        public async Task<List<Customer>> GetCustomersAsync()
        {
            return await _customerContext.Customers.ToListAsync();
        }

        public List<Customer> GetCustomers()
        {
            return _customerContext.Customers.ToList();
        }
    }

I would expect my second implementation to also work asynchronously. Could anyone help me understand please? What am I missing here? Thanks in advance for the help!

CodePudding user response:

It depends on your database if ToListAsync() really/always is async. It may execute synchronously, depending on the provider, caching etc.

There is a simple fix:

private List<Customer> customers = new();

protected async override Task OnInitializedAsync()
{
   await Task.Delay(1);
   this.customers = await CustomerService.GetCustomersAsync();
}

The async Delay() allows the loading... message to be displayed.

Note that you might as well call GetCustomers(), without the Task.Run() though.

... from a Sqlite db

Here is an answer about sqlite, it does not actually support async operations. The EF provider just pretends.

  • Related