Page 16 - MSDN Magazine, May 2018
P. 16

random number, but you’d normally replace this code and com- pose a key based on app-defined logic. Typically this would be based on the activation arguments retrieved earlier. For example, if the activation arguments were of type FileActivatedEventArgs, the app might use the specified file name as part of the key. Once you’ve composed the key, you pass it to the FindOrRegister- InstanceForKey method, which returns an AppInstance object that represents an instance of this app. To determine which instance to return, the method does two things:
• It searches for an existing instance of the app that has already registered this key.
• If no existing instance has already registered this key, it registers this current instance with this key.
If you’ve successfully registered this instance, you can now just go ahead and do the normal app initialization. For a XAML app, this means calling Application.Start with a new instance of the App class. If some other instance has already registered this key, you can now redirect this activation to that instance instead, and allow this instance to terminate. For example, consider an app that edits files. If the user has Foo.doc open for edits in the app, and then attempts to open Foo.doc again, the app might choose to redirect the second activation to the instance that already has Foo.doc open—and pre- vent the user from opening the same file in multiple instances. The logic for deciding whether or not to redirect, and which instance to select as the redirection target, is entirely app-defined.
For XAML apps, the Main method is normally auto-generated and hidden from the developer. This behavior is suppressed in the “multi-instance with redirection” template. If you’re updating an existing app, you can suppress the default Main by adding DISABLE_XAML_GENERATED_MAIN to the list of conditional compilation symbols in the build properties for the app. In some app types—for example, a C++ DirectX app—the Main function isn’t hidden. Apart from that, a DirectX app’s use of the new APIs follows the same patterns as in the XAML example.
Note that an app can only use the GetActivatedEventArgs and RedirectActivationTo methods during Main; if these are called any- where else, they will fail. This is because if you want to take part in activation redirection, you need to do this extremely early in the life of the app process, and certainly before any windows are created.
On the other hand, you can use the remaining AppInstance methods and properties at any time. In particular, you can use FindOrRegisterInstanceForKey to update the key for the current instance whenever you need to. For example, if your key was based on a file name, and you later close this file, you’d update your key registration at that time. You can also use the Unregister method to unregister completely if for some reason you no longer want this particular instance to take part in activation redirection. Also, at any time, you can use the AppInstance.GetInstances method to get a list of all registered instances of your app, including their keys, so that you can reason about their state.
Additional Considerations
Multi-instancing is a major enhancement, and the initial release covers only the major scenarios. Specifically, support is included for multi-instancing a foreground app, console apps, and most
out-of-process background tasks including app services. However, there’s no support in this release for ApplicationTrigger tasks or any in-proc background tasks.
During development, Microsoft spent considerable time testing a broad range of existing Store apps to see how they’d perform when multi-instanced. From this, Microsoft learned that apps fall into three broad categories:
• Apps that have no reason to be multi-instanced. These apps just won’t opt in to the feature.
• Apps that want to be multi-instanced, and continue to function correctly without any code changes. These apps can simply opt in to multi-instancing and call it done.
• Apps that want to be multi-instanced, but need to do work to allow for the differences in execution model.
For XAML apps,
the Main method is normally auto-generated and hidden from the developer.
The common issue with apps in the third category is that they’re using some central resource—perhaps a cache, or a database, or other file—and when single-instanced they’ve been safely assuming that the app has exclusive access to this resource. Once they opt in to multi-instancing, there may be multiple instances attempting to access the resource. In this scenario, the app needs to do work to synchronize access, locking reads and writes, and so on—in other words, all the usual synchronization issues that traditional Win32 apps need to consider.
As an obvious example, consider the use of the app’s local stor- age. This is an example of a resource where access is constrained on a package basis, not a process basis—and of course all instances of an app share the same package. Although each instance of the app is running as a separate process, they will all use the same local storage and settings, as represented by the Application- Data.Current API. If you’re performing data access operations in local storage, you should consider how to protect against clashes. One option is to use instance-unique files, where one instance’s operations can’t conflict with any other’s. Alternatively, if you want to use a common file across multiple instances, you should lock and unlock access to the file appropriately. You can use standard mechanisms such as a named Mutex for this.
Console UWP Apps
Another obvious gap in the UWP landscape is the ability to create a headless console app. In Win32 and other environments, you can create a command-line tool that uses the console window for input and output. So, we added this support also. Again, there’s a new Visual Studio project template, and as with multi-instanced apps, this generates additional manifest entries. This feature is also restricted to Desktop and IoT—not least because only those SKUs actually
12 msdn magazine
Universal Windows Platform


































































































   14   15   16   17   18