Dispatch exceptions to the sync context#28936
Conversation
Another common scenario is if a component wants to start an async operation in a fire-and-forget way. So it's not going to await the Task, and it doesn't get back a result, but if the operation fails it wants to treat it as a lifecycle exception to put the whole component into a faulted state, or to terminate the circuit (if it's Blazor Server and there is no error boundary), and to trigger the same logging that occurs for lifecycle exceptions. Example: <button @onclick="SendReport">Send report</button>
@code {
void SendReport()
{
// In most cases you'd want to await this task and update the UI afterwards to say the operation completed
// But for this example, we're doing it in a fire-and-forget way, so we don't return a Task from this method
_ = SendReportFireAndForgetAsync();
}
async Task SendReportFireAndForgetAsync()
{
try
{
await ReportSender.SendAsync();
}
catch (Exception ex)
{
// Because we intentionally discarded the task above, any async failures would occur off the normal
// lifecycle call stack, and hence would not be seen by Blazor. We can treat them like lifecycle method
// exceptions by explicitly dispatching them back to the component.
await DispatchExceptionAsync(ex);
}
}
} |
|
Thanks @SteveSandersonMS ... I'll make these updates Monday morning and ping u back. |
|
@SteveSandersonMS ... Ready ...
|
Co-authored-by: Steve Sanderson <SteveSandersonMS@users.noreply.github.com>
Fixes #28933
Notes ...
I felt building off of the prior example makes sense. Presumably, many readers will have just tested out the prior section's example, so they can just build on that experience to see this API in action.
Here's what this new example builds off of ...
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-7.0#invoke-component-methods-externally-to-update-state
There's one thing in Steve's remarks that I don't understand ...
Cross-ref: [API Proposal] Allow Dispatching to Blazor Renderer Sync Context aspnetcore#46068 (comment)
... but error boundaries (getting them to light up here) is about trapping unhandled exceptions. The example that I have on this PR is throwing in the
TimerServiceto show how the exception can be forwarded to the Blazor sync context.... also Halter said right after that ...
... but again, you can do both. You can take action on it, just in the sense that you're processing it in the external code (e.g., log it), and then flow it unhandled to Blazor for the error boundary to trip on purpose. I don't see why this isn't a valid approach.
I guess what I'm saying is that if these PU remarks are right, we don't want to show this example based on an exception in
TimerService...TimerServiceshould handle its exceptions entirely and flow back something to the caller for processing in the Razor component on an error, not allow the unhandled exception to trip the error boundary. What I have here might be considered as an implied anti-pattern 🙈 and should be replaced with a different example.Besides that, is there some other or additional scenario that you'd like to show? I like this one, but I'm just pitching it as a possibility because the prior example is so good (IMO) and feeds right into the usefulness of this API AFAICT.
Internal previews