Skip to content

Commit e2e6f6c

Browse files
Fire and forget BlazorWebView disposal by default (#25430)
1 parent e8b5dc6 commit e2e6f6c

File tree

4 files changed

+55
-23
lines changed

4 files changed

+55
-23
lines changed

src/BlazorWebView/src/Maui/Android/BlazorWebViewHandler.Android.cs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@ protected override AWebView CreatePlatformView()
6161

6262
private const string AndroidFireAndForgetAsyncSwitch = "BlazorWebView.AndroidFireAndForgetAsync";
6363

64-
private static bool IsAndroidFireAndForgetAsyncEnabled =>
65-
AppContext.TryGetSwitch(AndroidFireAndForgetAsyncSwitch, out var enabled) && enabled;
66-
6764
protected override void DisconnectHandler(AWebView platformView)
6865
{
6966
platformView.StopLoading();
@@ -77,19 +74,25 @@ protected override void DisconnectHandler(AWebView platformView)
7774
.DisposeAsync()
7875
.AsTask()!;
7976

80-
if (IsAndroidFireAndForgetAsyncEnabled)
81-
{
82-
// If the app is configured to fire-and-forget via an AppContext Switch, we'll do that.
83-
disposalTask.FireAndForget();
84-
}
85-
else
77+
// When determining whether to block on disposal, we respect the more specific AndroidFireAndForgetAsync switch
78+
// if specified. If not, we fall back to the general UseBlockingDisposal switch, defaulting to false.
79+
var shouldBlockOnDispose = AppContext.TryGetSwitch(AndroidFireAndForgetAsyncSwitch, out var enableFireAndForget)
80+
? !enableFireAndForget
81+
: IsBlockingDisposalEnabled;
82+
83+
if (shouldBlockOnDispose)
8684
{
87-
// Otherwise by default, we'll synchronously wait for the disposal to complete. This can cause
88-
// a deadlock, but is the original behavior.
85+
// If the app is configured to block on dispose via an AppContext switch,
86+
// we'll synchronously wait for the disposal to complete. This can cause a deadlock.
8987
disposalTask
9088
.GetAwaiter()
9189
.GetResult();
9290
}
91+
else
92+
{
93+
// Otherwise, by default, we'll fire-and-forget the disposal task.
94+
disposalTask.FireAndForget(_logger);
95+
}
9396

9497
_webviewManager = null;
9598
}

src/BlazorWebView/src/Maui/BlazorWebViewHandler.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ namespace Microsoft.AspNetCore.Components.WebView.Maui
1313
#endif
1414
public partial class BlazorWebViewHandler
1515
{
16+
private const string UseBlockingDisposalSwitch = "BlazorWebView.UseBlockingDisposal";
17+
18+
private static bool IsBlockingDisposalEnabled =>
19+
AppContext.TryGetSwitch(UseBlockingDisposalSwitch, out var enabled) && enabled;
20+
1621
/// <summary>
1722
/// This field is part of MAUI infrastructure and is not intended for use by application code.
1823
/// </summary>

src/BlazorWebView/src/Maui/Windows/BlazorWebViewHandler.Windows.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Microsoft.Extensions.FileProviders;
77
using Microsoft.Extensions.Logging;
88
using Microsoft.Extensions.Logging.Abstractions;
9+
using Microsoft.Maui;
910
using Microsoft.Maui.Dispatching;
1011
using Microsoft.Maui.Handlers;
1112
using WebView2Control = Microsoft.UI.Xaml.Controls.WebView2;
@@ -30,13 +31,24 @@ protected override void DisconnectHandler(WebView2Control platformView)
3031
{
3132
if (_webviewManager != null)
3233
{
33-
// Dispose this component's contents and block on completion so that user-written disposal logic and
34-
// Blazor disposal logic will complete.
35-
_webviewManager?
34+
// Start the disposal...
35+
var disposalTask = _webviewManager?
3636
.DisposeAsync()
37-
.AsTask()
38-
.GetAwaiter()
39-
.GetResult();
37+
.AsTask()!;
38+
39+
if (IsBlockingDisposalEnabled)
40+
{
41+
// If the app is configured to block on dispose via an AppContext switch,
42+
// we'll synchronously wait for the disposal to complete. This can cause a deadlock.
43+
disposalTask
44+
.GetAwaiter()
45+
.GetResult();
46+
}
47+
else
48+
{
49+
// Otherwise, by default, we'll fire-and-forget the disposal task.
50+
disposalTask.FireAndForget();
51+
}
4052

4153
_webviewManager = null;
4254
}

src/BlazorWebView/src/Maui/iOS/BlazorWebViewHandler.iOS.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Microsoft.Extensions.FileProviders;
99
using Microsoft.Extensions.Logging;
1010
using Microsoft.Extensions.Logging.Abstractions;
11+
using Microsoft.Maui;
1112
using Microsoft.Maui.Dispatching;
1213
using Microsoft.Maui.Handlers;
1314
using UIKit;
@@ -127,13 +128,24 @@ protected override void DisconnectHandler(WKWebView platformView)
127128

128129
if (_webviewManager != null)
129130
{
130-
// Dispose this component's contents and block on completion so that user-written disposal logic and
131-
// Blazor disposal logic will complete.
132-
_webviewManager?
131+
// Start the disposal...
132+
var disposalTask = _webviewManager?
133133
.DisposeAsync()
134-
.AsTask()
135-
.GetAwaiter()
136-
.GetResult();
134+
.AsTask()!;
135+
136+
if (IsBlockingDisposalEnabled)
137+
{
138+
// If the app is configured to block on dispose via an AppContext switch,
139+
// we'll synchronously wait for the disposal to complete. This can cause a deadlock.
140+
disposalTask
141+
.GetAwaiter()
142+
.GetResult();
143+
}
144+
else
145+
{
146+
// Otherwise, by default, we'll fire-and-forget the disposal task.
147+
disposalTask.FireAndForget(_logger);
148+
}
137149

138150
_webviewManager = null;
139151
}

0 commit comments

Comments
 (0)