[Blazor Hybrid] Consider guarding HandleComponentException when Renderer is Disposed
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
I originally reported this issue on the .NET MAUI side: https://github.com/dotnet/maui/issues/34855. While investigating, I encountered several exceptions, and I believe the specific case described below belongs in this repository.
Consider the following:
```csharp
@code {
private bool _loading;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
_ = BackgroundWork();
}
private async Task BackgroundWork()
{
_loading = true;
await InvokeAsync(StateHasChanged);
try
{
await Task.Delay(5000);
throw new Exception("Exception");
}
catch (Exception exception)
{
// MainLayout needs to be wrapped in ErrorBoundary
await DispatchExceptionAsync(exception);
}
finally
{
_loading = false;
await InvokeAsync(StateHasChanged);
}
}
}
```
If the browser is closed while `Task.Delay` is still in progress and the WebView is **explicitly disposed**(!!!) via `BlazorWebView.DisposeAsync()`, an exception `Renderer does not have a component with ID XX` is thrown.
If the WebView is not explicitly disposed, a different exception occurs instead, related to the `WebView2` control already being disposed.
This behavior has been reproduced in WPF. I have not tested WinForms, but I expect similar behavior since most of the code is shared (aside from the dispatcher). I have also not verified whether this affects MAUI Hybrid.
### Expected Behavior
Not to throw exception when webview is disposed.
### Steps To Reproduce
This issue can be reproduced using a shared sample with .NET MAUI.
1. Fork the repository: https://github.com/ScarletKuro/WpfIssueThreading
2. In `App.xaml.cs`, uncomment the line `mainWindow.DisposeAsync();`
3. Run the application
4. Close the window while it says loading
5. Observe the exception: `Renderer does not have a component with ID XX`
### Exceptions (if any)
```
Exception has been thrown by the target of an invocation. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.ArgumentException: The renderer does not have a component with ID 15.
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetRequiredComponentState(Int32 componentId)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.HandleComponentException(Exception exception, Int32 componentId)
at Microsoft.AspNetCore.Components.RenderHandle.<>c__DisplayClass22_0.b__0()
at Microsoft.AspNetCore.Components.WebView.Wpf.WpfDispatcher.InvokeAsync(Action workItem)
at SalesSystem.Web.Pages.Kiosk.GetCouponsInBackground() in C:\Users\Kuro\source\repos\kiisu\src\SalesSystem.Web\Pages\Kiosk.razor.cs:line 129
at SalesSystem.Web.Pages.Kiosk.GetCouponsInBackground() in C:\Users\Kuro\source\repos\kiisu\src\SalesSystem.Web\Pages\Kiosk.razor.cs:line 138
at Microsoft.AspNetCore.Components.WebView.Wpf.WpfDispatcher.<>c.<.cctor>b__8_0(Exception exception)
at InvokeStub_Action`1.Invoke(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
--- End of inner exception stack trace ---
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
System.Object:
System.ArgumentException: The renderer does not have a component with ID 15.
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetRequiredComponentState(Int32 componentId)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.HandleComponentException(Exception exception, Int32 componentId)
at Microsoft.AspNetCore.Components.RenderHandle.<>c__DisplayClass22_0.b__0()
at Microsoft.AspNetCore.Components.WebView.Wpf.WpfDispatcher.InvokeAsync(Action workItem)
at SalesSystem.Web.Pages.Kiosk.GetCouponsInBackground() in C:\Users\Kuro\source\repos\kiisu\src\SalesSystem.Web\Pages\Kiosk.razor.cs:line 129
at SalesSystem.Web.Pages.Kiosk.GetCouponsInBackground() in C:\Users\Kuro\source\repos\kiisu\src\SalesSystem.Web\Pages\Kiosk.razor.cs:line 138
at Microsoft.AspNetCore.Components.WebView.Wpf.WpfDispatcher.<>c.<.cctor>b__8_0(Exception exception)
at InvokeStub_Action`1.Invoke(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
```
### .NET Version
10.0.201
### Anything else?
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.