asp.net-coreexceptionblazorsynchronizationcontext

When do we dispatch exceptions to synchronization context in blazor?


In the following example from Microsoft Blazor docs, they state that exceptions that occur in tasks that do not run in the synchronization context need to be sent back to the synchronization context in order for things like error boundaries to be applied. That makes perfect sense, but then they then proceed to give the following example:

<button @onclick="SendReport">Send report</button>

@code {
    private void SendReport()
    {
        _ = SendReportAsync();
    }

    private async Task SendReportAsync()
    {
        try
        {
            await ReportSender.SendAsync();
        }
        catch (Exception ex)
        {
            await DispatchExceptionAsync(ex);
        }
    }
}

However, since SendReportAsync() is guaranteed to be executed on blazor's synchronization context (afterall the source of this function call is a button click), and because in our await ReportSender.SendAsync() we DO NOT use ConfigureAwait(false), wouldn't this guarantee that all code following await ReportSender.SendAsync() will also be executed on the SynchronizationContext? Thus if all code in the try block is executed in Blazor's Synchronization Context, why do we need to dispatch the exception with DispatchExceptionAsync(ex)?


Solution

  • The problem is (of course):

    private void SendReport()
    {
       _ = SendReportAsync();
    
       // we (can) get here before SendReportAsync is finished.
    }
    

    By not awaiting the Task there is now a 'logical thread' that cannot return anything. Suppose it returned int instead of void. There is no way you could use that value.

    Same for the exception. It will just get lost somewhere and cannot be handled by calling code.