Skip to content

Commit

Permalink
Fire and forget BlazorWebView disposal by default (#25430)
Browse files Browse the repository at this point in the history
  • Loading branch information
MackinnonBuck authored Oct 22, 2024
1 parent e8b5dc6 commit e2e6f6c
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 23 deletions.
25 changes: 14 additions & 11 deletions src/BlazorWebView/src/Maui/Android/BlazorWebViewHandler.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,6 @@ protected override AWebView CreatePlatformView()

private const string AndroidFireAndForgetAsyncSwitch = "BlazorWebView.AndroidFireAndForgetAsync";

private static bool IsAndroidFireAndForgetAsyncEnabled =>
AppContext.TryGetSwitch(AndroidFireAndForgetAsyncSwitch, out var enabled) && enabled;

protected override void DisconnectHandler(AWebView platformView)
{
platformView.StopLoading();
Expand All @@ -77,19 +74,25 @@ protected override void DisconnectHandler(AWebView platformView)
.DisposeAsync()
.AsTask()!;

if (IsAndroidFireAndForgetAsyncEnabled)
{
// If the app is configured to fire-and-forget via an AppContext Switch, we'll do that.
disposalTask.FireAndForget();
}
else
// When determining whether to block on disposal, we respect the more specific AndroidFireAndForgetAsync switch
// if specified. If not, we fall back to the general UseBlockingDisposal switch, defaulting to false.
var shouldBlockOnDispose = AppContext.TryGetSwitch(AndroidFireAndForgetAsyncSwitch, out var enableFireAndForget)
? !enableFireAndForget
: IsBlockingDisposalEnabled;

if (shouldBlockOnDispose)
{
// Otherwise by default, we'll synchronously wait for the disposal to complete. This can cause
// a deadlock, but is the original behavior.
// If the app is configured to block on dispose via an AppContext switch,
// we'll synchronously wait for the disposal to complete. This can cause a deadlock.
disposalTask
.GetAwaiter()
.GetResult();
}
else
{
// Otherwise, by default, we'll fire-and-forget the disposal task.
disposalTask.FireAndForget(_logger);
}

_webviewManager = null;
}
Expand Down
5 changes: 5 additions & 0 deletions src/BlazorWebView/src/Maui/BlazorWebViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ namespace Microsoft.AspNetCore.Components.WebView.Maui
#endif
public partial class BlazorWebViewHandler
{
private const string UseBlockingDisposalSwitch = "BlazorWebView.UseBlockingDisposal";

private static bool IsBlockingDisposalEnabled =>
AppContext.TryGetSwitch(UseBlockingDisposalSwitch, out var enabled) && enabled;

/// <summary>
/// This field is part of MAUI infrastructure and is not intended for use by application code.
/// </summary>
Expand Down
24 changes: 18 additions & 6 deletions src/BlazorWebView/src/Maui/Windows/BlazorWebViewHandler.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Maui;
using Microsoft.Maui.Dispatching;
using Microsoft.Maui.Handlers;
using WebView2Control = Microsoft.UI.Xaml.Controls.WebView2;
Expand All @@ -30,13 +31,24 @@ protected override void DisconnectHandler(WebView2Control platformView)
{
if (_webviewManager != null)
{
// Dispose this component's contents and block on completion so that user-written disposal logic and
// Blazor disposal logic will complete.
_webviewManager?
// Start the disposal...
var disposalTask = _webviewManager?
.DisposeAsync()
.AsTask()
.GetAwaiter()
.GetResult();
.AsTask()!;

if (IsBlockingDisposalEnabled)
{
// If the app is configured to block on dispose via an AppContext switch,
// we'll synchronously wait for the disposal to complete. This can cause a deadlock.
disposalTask
.GetAwaiter()
.GetResult();
}
else
{
// Otherwise, by default, we'll fire-and-forget the disposal task.
disposalTask.FireAndForget();
}

_webviewManager = null;
}
Expand Down
24 changes: 18 additions & 6 deletions src/BlazorWebView/src/Maui/iOS/BlazorWebViewHandler.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Maui;
using Microsoft.Maui.Dispatching;
using Microsoft.Maui.Handlers;
using UIKit;
Expand Down Expand Up @@ -127,13 +128,24 @@ protected override void DisconnectHandler(WKWebView platformView)

if (_webviewManager != null)
{
// Dispose this component's contents and block on completion so that user-written disposal logic and
// Blazor disposal logic will complete.
_webviewManager?
// Start the disposal...
var disposalTask = _webviewManager?
.DisposeAsync()
.AsTask()
.GetAwaiter()
.GetResult();
.AsTask()!;

if (IsBlockingDisposalEnabled)
{
// If the app is configured to block on dispose via an AppContext switch,
// we'll synchronously wait for the disposal to complete. This can cause a deadlock.
disposalTask
.GetAwaiter()
.GetResult();
}
else
{
// Otherwise, by default, we'll fire-and-forget the disposal task.
disposalTask.FireAndForget(_logger);
}

_webviewManager = null;
}
Expand Down

0 comments on commit e2e6f6c

Please sign in to comment.