0
votes

I recently asked a question regarding the difference between await Task.Run(StateHasChanged); and await InvokeAsync(StateHasChanged); in Blazor wasm here.

The conclusion was that await Task.Run(StateHasChanged); was incorrect and should be avoided; using it would produce the same results as await InvokeAsync(StateHasChanged); however would fall over when threads are available (The accepted answer explains in detail).

I've updated my codebase to use await InvokeAsync(StateHasChanged);, however I've discovered there is actually a difference in outcome between the two.

Here's a minimal reproduction of the issue in my application:

Parent

<h1>Parent: @title</h1>

<button class="btn btn-primary" @onclick="() => SetBool(true)">True</button>
<button class="btn btn-primary" @onclick="() => SetBool(false)">False</button>

<Child Bool="@Bool" @ref="Child"></Child>

@code {
    private bool Bool = false;
    private Child Child;
    private string title;

    private async void SetBool(bool name)
    {
        Bool = name;
        title = Bool ? "True" : "False";
        // NOTE: This will work as expected; Child will be updated with the Parent
        // await Task.Run(StateHasChanged);
        // NOTE: This will only update the Child the second time it is clicked
        await InvokeAsync(StateHasChanged);
        await Child.Trigger();
    }

}

Child

<h3>Child: @title</h3>

@code {
    [Parameter]
    public bool Bool { set; get; } = false;
    private string title;

    public async Task Trigger()
    {
        title = Bool ? "True" : "False";
        await InvokeAsync(StateHasChanged);
    }
}

Clicking either the True or False button in the parent should update the Bool value in both the parent and child. Note that the title variable is only used for a visual display of the Bool value.

Using await Task.Run(StateHasChanged); will cause both the parent and child's state to be updated at the same time. On the other hand await InvokeAsync(StateHasChanged); will update the parent, but not the child; it takes two clicks of the a button to get the respective value in the child component.

Is there an issue with how I'm passing this value to the child component?

Note that using await Task.Run(StateHasChanged); isn't an option; doing so means I can't test the component with bUnit.

The reproduction code is available here.