Search code examples
c#asp.net.netasync-awaittask

Awaiting an Event Callback from in a task quits executing code


I have a Parent and a Child Razor component, the child has a Parameter that is of type EventCallback. If I have an async Task called from a synchronous function (using Task.Run) after I await the .InvokeAsync no further lines of code run.

Parent Component:

@page "/"
@inject NavigationManager navigationManager

<PageTitle>Home</PageTitle>

<Child OnChildClick="() => OnChildClick(newMessage)" />

<p>@_message</p>
@code
{
    private string _message = "test";
    private string newMessage = "new test";

    private void OnChildClick(string message)
    {
        _message = message;
        InvokeAsync(StateHasChanged);
    }
}

Child Component

<h3>Child</h3>

<MudButton OnClick="OnClick">Click me</MudButton>

@code {
    [Parameter]
    public EventCallback OnChildClick { get; set; }

    private void OnClick()
    {
        Task.Run(() => OnClickDoThing());
    }

    private async Task OnClickDoThing()
    {
        await OnChildClick.InvokeAsync();

        Console.WriteLine("Child clicked"); // This will not be called, why?
    }
}

As you can see I commented on the Console.WriteLine. If I instead make the OnClick function async and just await the OnClickDoThing it works fine, but in a Task.Run, it doesn't. Can someone help me and explain the reason behind this? I assume I don't understand Task.Run well enough.


Solution

  • Task.Run() returns a new Task. A task won't proceed past the first await where IsCompleted is false without someone awaiting it at a higher level. That's why it works in one case and not the other.

    You can try this out in a console application where your dependencies will be simpler and you'll get a better idea of how things are working, or not as the case might be.

    Disclaimer: assume default task scheduler and other shenanigans.