-
Notifications
You must be signed in to change notification settings - Fork 344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improvements to the instancing redirection API #1709
Comments
Tracking internally 36907792. |
Seems promising. Any estimates to bring it up soon? |
We don't have a firm date for this yet. That said, we are interested in any feedback, and to gauge the level of demand for this. |
It has been a while. I have a branch out with The spec has been updated with RedirectActivationTo. I would like this reviewed please. |
I've decided not to work on the first issue, about redirecting to a terminating instance because I can't repro that. I've tried
In all three cases no crash happened. I do believe safe-guards were put in place to protect against this. However, if a repro can be made, please let me know I'll get working on a fix. |
@jonwis and @DrusTheAxe |
I was able to repro this with a super-simple C# console app that declared main to be STA. |
Are there any plans for the near future to improve this? I just came across this problem while working with push notifications and their handlers when the user clicks them. |
I don't believe anything is planned in the immediate future to work on this issue.
From: nicop85 ***@***.***>
Sent: Thursday, May 18, 2023 6:41 AM
To: microsoft/WindowsAppSDK ***@***.***>
Cc: Scott Darnell ***@***.***>; Assign ***@***.***>
Subject: Re: [microsoft/WindowsAppSDK] Improvements to the instancing redirection API (Issue #1709)
Is there any plans for the near future to improve this?
I just came across this problem while working with push notifications and their handlers when the user clicks them.
-
Reply to this email directly, view it on GitHub<#1709 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AE4I5UTRB4ZQZ3QQNZNOAT3XGYRHTANCNFSM5HG5RCWA>.
You are receiving this because you were assigned.Message ID: ***@***.******@***.***>>
|
RedirectActivationTo
Overview
The API spec [here](https://github.com/microsoft/WindowsAppSDK/blob/main/specs/AppLifecycle/Instancing/AppLifecycle SingleMulti-Instancing.md) describes how the Windows App SDK brings the single-/
multi-instancing API support from UWP to non-UWP apps. One of the key
methods is RedirectActivationToAsync. This document describes some problems
with the current API design, and proposals for mitigation.
The purpose of the API is that when an app instance starts, it can discover other
running instances of itself and conditionally redirect its own activation to one of
those other instances. This enables an app to be single-instanced or selectively
multi-instanced, based on the app’s own logic.
This is very similar to the UWP RedirectActivationTo method, with 2 differences:
The UWP method takes no parameters, and the target instance receives the
exact same activation arguments that the redirecting instance received.
Conversely, the Windows App SDK version allows the app to choose whether
to pass the arguments it received or to modify or replace them.
In the UWP implementation, redirection is a terminal operation: after the
RedirectActivationTo call, the platform terminates the calling instance. In
the Windows App SDK, redirection is not necessarily a terminal operation.
In most cases, we expect the redirecting instance to simply return from
Main after redirecting, effectively terminating itself – but the app has the
option to continue if it wishes.
Problems
There are 2 main problems with the Windows App SDK API in its current form:
Terminating target. There’s a race where an instance of the app attempts to
redirect to another instance, but that other instance happens to be in the
process of terminating. This causes the calling instance to crash.
STA blocking. In many app types, calling the redirection method requires
additional threading/synchronization work.
We expect the redirect call to happen very early – and before doing any
initialization, window creation, etc, that would in most cases be redundant
if the app is redirecting. Apps are therefore encouraged to do this in Main.
The redirection method is async, but we need the caller to wait for it to
complete before terminating, otherwise the redirection doesn’t succeed.
Some app types specify that Main must run in an STA. If we wait on the
async call, we’ll block the STA, which for some app types causes a runtime
assert, and for other types has unpredictable consequences.
Proposed solutions
For the 2 problems, we propose 2 solutions: that is, to add 2 new methods to
the AppInstance class.
Terminating target
This is the simpler of the 2 problems to solve. The proposal is for the internal
implementation of the redirect operation to catch the case where the target
instance is terminating, and instead of propagating the error to the caller,
convert this to a bool return value (where false indicates that the redirection
failed). This requires either updating the method signature, or adding a new
method. Updating the existing method would constitute a breaking change, so
the preferred option is to add a second method.
The existing method is defined as:
…the additional method could be defined like this:
STA blocking
It is possible for the app to work around the STA-blocking problem, and the exact
mitigations depend on the app type:
Declare Main to be async, and use the await pattern. This is only available in
C# apps, and only works correctly in WinForms apps. It is not
an option for C++ apps, and it does not work for C# WPF apps,
nor for C# WinUI apps.
Explicitly write the code that async/await are doing: that is, move the redirect
call to another thread, use an event to signal when it is complete, and use a
non-blocking method to wait on the signal (eg, CoWaitForMultipleObjects or
MsgWaitForMultipleObjects). This works for all app types.
Here are all the app types under consideration for the Windows App SDK (note:
packaged vs unpackaged makes no difference in this context):
Here’s an example of the code you can use in Windows Forms:
Here’s an example of the kind of code you’d use in C++ WinUI:
The C# equivalent for C#/WinUI and WPF apps would look like this (p/invoke declarations omitted):
Asking app developers to write additional threading/synchronization code when
they want to use the redirection API suggests that the redirection API needs
improvement:
The required threading/synchronization code is painful and error-prone.
In the case of C++/WinRT it also requires a thorough understanding of
C++/WinRT coroutines and special event types.
For C++/WinRT, the recommendation is to use the Windows.Implementation.Library
(WIL), so you’d also need to include the WIL NuGet package which the app
might not otherwise need.
The developer needs to understand whether their code is running in an STA
– and this is not always obvious.
WPF has the additional issue that you can declare main to be async, but this
actually causes the [STAThread] attribute to be ignored, and WPF window
creation immediately fails.
C#/WinUI has the additional issue that you can declare main to be async, but
this actually prevents Narrator from reading the XAML elements, so this is an
accessibility concern.
If you want to use the same threading/synchronization mechanisms for a WPF
or C#/WinUI app as shown above, you’d need to p/invoke the relevant native
APIs because .NET does not include all the APIs you’d need.
Different app types have different mitigations available to them, which will
only add to developer confusion.
All this makes for a very poor developer experience. We therefore propose to
update the API as follows. From an app developer’s perspective, it would be much
more convenient to be able to do something like this:
To enable this, we propose to add a non-async RedirectActivationTo method to
the AppInstance class, that would do the functional equivalent of this:
Documentation would then encourage developers to use RedirectActivationTo
instead of the existing RedirectActivationToAsync or the proposed new
RedirectActivationToWithResultAsync for all app types whenever they need to
do the redirection logic in Main (which we believe is the most common case).
The text was updated successfully, but these errors were encountered: