Skip to content

Commit 7ccd2f5

Browse files
committed
Add 'AppServiceHost.OnCloseRequested' method
1 parent 70c49d1 commit 7ccd2f5

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

components/AppServices/src/AppServiceHost.cs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
using System.Runtime.CompilerServices;
99
using System.Threading;
1010
using System.Threading.Tasks;
11+
using CommunityToolkit.AppServices.Helpers;
1112
using Windows.ApplicationModel;
1213
using Windows.ApplicationModel.Activation;
1314
using Windows.ApplicationModel.AppService;
1415
using Windows.ApplicationModel.Background;
1516
using Windows.Foundation.Collections;
1617
using Windows.Foundation.Metadata;
1718
using Windows.System.Profile;
18-
using CommunityToolkit.AppServices.Helpers;
19+
using Windows.UI.Core.Preview;
1920

2021
#pragma warning disable CA1068
2122

@@ -143,6 +144,58 @@ public bool OnBackgroundActivated(BackgroundActivatedEventArgs args)
143144
return true;
144145
}
145146

147+
/// <summary>
148+
/// Handles the app service host shutdown when <see cref="SystemNavigationManagerPreview.GetForCurrentView().CloseRequested"/> is raised.
149+
/// </summary>
150+
/// <param name="args">The args for the close request.</param>
151+
/// <remarks>
152+
/// <para>
153+
/// This method should be used as follows (from <c>App.xaml.cs</c>):
154+
/// <code language="cs">
155+
/// private void OnCloseRequested(object? sender, SystemNavigationCloseRequestedPreviewEventArgs e)
156+
/// {
157+
/// // Any other work, possibly marking the request as handled
158+
///
159+
/// DesktopExtension.OnCloseRequested(e);
160+
/// }
161+
/// </code>
162+
/// </para>
163+
/// <para>
164+
/// The app might be holding a deferral for the app service connection to the extension process, which is currently only completed when the
165+
/// connection is closed. This means that when the application is closed, that deferral will actually try to keep the connection alive, until
166+
/// the OS will eventually force terminate it. This will cause following launches of the app to be delayed until the previous process is
167+
/// completely gone, meaning that closing the app and immediately reopening it will cause it to remain stuck at the splash screen for a few
168+
/// seconds. Note that during this time, no app code is actually executed, it's just that the OS is waiting to terminate the existing connection
169+
/// and fully close the previous instance before allowing a new one to be started. To avoid this issue, this method takes care of fully closing
170+
/// any existing connection (by canceling its associated deferral), when the app is about to exit. This avoids the OS timeout for the connection.
171+
/// </para>
172+
/// </remarks>
173+
public void OnCloseRequested(SystemNavigationCloseRequestedPreviewEventArgs args)
174+
{
175+
// Do nothing if the close request has been handled
176+
if (args.Handled)
177+
{
178+
return;
179+
}
180+
181+
// Remove the registered connection handlers
182+
if (_appServiceConnection is { } appServiceConnection)
183+
{
184+
appServiceConnection.ServiceClosed -= AppServiceConnection_ServiceClosed;
185+
appServiceConnection.RequestReceived -= AppServiceConnection_RequestReceived;
186+
187+
_appServiceConnection = null;
188+
}
189+
190+
// Cancel the deferral, if present
191+
if (_appServiceDeferral is { } appServiceDeferral)
192+
{
193+
appServiceDeferral.Complete();
194+
195+
_appServiceDeferral = null;
196+
}
197+
}
198+
146199
/// <summary>
147200
/// Creates a new <see cref="AppServiceRequest"/> for a given operation.
148201
/// </summary>

0 commit comments

Comments
 (0)