Blazor Webassembly - StateAsChanged not fire using IAsyncEnumerable · Issue #43098 · dotnet/aspnetcore (original) (raw)

Is there an existing issue for this?

Describe the bug

Hello,

I am trying to use a controller that returns an IAsyncEnumerable from a webassembly Razor application.

In this repo https://github.com/GLuca74/TestBlazorWebAssembyIAsyncEnumerable there is a simply Web Api Application with the WeatherForecastController that have the Get method that resutrns 1 milion of int as IAsyncEnuverable

    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        [HttpGet]
        public async IAsyncEnumerable<int> Get()
        {
            for (int i = 0; i < 1000000; i++)
            {
                yield return i;
            }
        }
    }

In the Balzor webassembly application, the counter Page contain the code that use the controller :

<h1>Counter</h1>
<span>@Count</span>
<table class="table">
        <thead>
            <tr>
                <th>Title</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var n in Source) 
            {
                <tr>
                    <td>@n</td>
                </tr>
            }
        </tbody>
    </table>


@code {
    private int Count;
    public List<int> Source;

    protected async override Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        Source = new List<int>();
        await foreach (int n in GetData())
        {
            Count = Count + 1;
            Source.Add(n);
            if ((Count % 10) == 0)
            {
                //await Task.Delay(1);
                InvokeAsync(StateHasChanged); // StateHasChanged();
            }
        }
    }

    public async IAsyncEnumerable<int> GetData(CancellationToken cancellationToken = default)
    {
        using (HttpClient httpClient = new HttpClient())
        {
            httpClient.BaseAddress = new Uri(@"https://localhost:7034/");
            httpClient.DefaultRequestHeaders.Accept.Clear();
            httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
            httpClient.Timeout = new TimeSpan(1, 0, 0);
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "weatherforecast");
            request.SetBrowserResponseStreamingEnabled(true);
            using (var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false))
            {
                if (!response.IsSuccessStatusCode)
                {
                    HttpRequestException ex = new HttpRequestException(response.Content.ReadAsStringAsync().GetAwaiter().GetResult(), null, response.StatusCode);
                    throw ex;
                }
                Stream responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
                IAsyncEnumerable<int> intResponse = JsonSerializer.DeserializeAsyncEnumerable<int>(responseStream, new JsonSerializerOptions{PropertyNameCaseInsensitive = true}, cancellationToken);
                await foreach (int n in intResponse)
                {
                    yield return n;
                }
            }
        }
    }
}

When the data is loaded, only one update of the UI is performed and the page remain locked. But if I call await Task.Delay(1) before call StateHasChanged all works and any update of the UI is performed.

Can I ask why the Delay is needed to let it works or wath is wrong with my code?

Expected Behavior

No response

Steps To Reproduce

No response

Exceptions (if any)

No response

.NET Version

No response

Anything else?

No response