Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе описывается создание многоэкземплярных приложений Universal Windows Platform (UWP).
Начиная с Windows 10 версии 1803 (10.0; Сборка 17134), ваше UWP-приложение может поддерживать несколько экземпляров. Если экземпляр многоэкземплярного приложения UWP уже запущен и поступает последующий запрос активации, платформа не активирует существующий экземпляр. Вместо этого он создаст новый экземпляр, выполняющийся в отдельном процессе.
Подписаться на поведение нескольких экземпляров
Если вы создаете новое приложение с несколькими экземплярами, вы можете установить Multi-Instance App Project Templates.VSIX, доступные в Visual Studio Marketplace. После установки шаблонов они будут доступны в диалоговом окне создания проекта в разделе Visual C# > Windows Universal (или Другие языки > Visual C++ > Windows Universal).
Замечание
Шаблон проекта приложения с несколькими экземплярами больше недоступен. Шаблон VSIX был удобством, поэтому вместо этого необходимо изменить существующий проект, как описано ниже. Обязательно добавьте константу DISABLE_XAML_GENERATED_MAIN в символы сборки проекта, так как это предотвращает создание сборки по умолчанию Main(). Это позволяет использовать специально написанную версию Main(), предназначенную для конкретного приложения.
Установлены два шаблона: приложение UWP для нескольких экземпляров, которое предоставляет шаблон для создания приложения с несколькими экземплярами, и приложение UWP для перенаправления нескольких экземпляров, которое обеспечивает дополнительную логику, чтобы можно было запускать новый экземпляр или выборочно активировать уже запущенный экземпляр. Например, возможно, вы хотите, чтобы в одно и то же время работал только один экземпляр при редактировании одного и того же документа, поэтому вы активируете экземпляр с открытым файлом, а не запускаете новый экземпляр.
Оба шаблона добавляют SupportsMultipleInstances в файл package.appxmanifest. Обратите внимание на префикс desktop4пространства имен: только проекты, предназначенные для настольных компьютеров, поддерживают многоуровневую настройку.
Замечание
Если приложение предназначено для Windows 10 версии 2004 (сборка 19041) или более поздней версии, вместо этого uap10:SupportsMultipleInstancesможно использовать новый desktop4:SupportsMultipleInstances атрибут. Пространство uap10 имен является предпочтительным подходом для новых приложений.
<Package
...
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
IgnorableNamespaces="uap mp desktop4">
...
<Applications>
<Application Id="App"
...
desktop4:SupportsMultipleInstances="true">
...
</Application>
</Applications>
...
</Package>
Перенаправление многоэкземплярной активации
Поддержка многократного развертывания приложений UWP выходит за рамки простой возможности запуска нескольких экземпляров приложения. Он позволяет настраивать в случаях, когда требуется выбрать, запускается ли новый экземпляр приложения или уже запущенный экземпляр. Например, если приложение запускается для изменения файла, который уже редактируется в другом экземпляре, может потребоваться перенаправить активацию в этот экземпляр вместо открытия другого экземпляра, который уже редактирует файл.
Чтобы увидеть это в действии, посмотрите это видео о создании приложений платформы UWP с несколькими экземплярами.
Шаблон приложения UWP Main. Ниже показан шаблон для Program.cs.
Свойство AppInstance.RecommendedInstance представляет предпочтительный экземпляр, предоставленный оболочкой, для этого запроса активации, если имеется один (или null, если его нет). Если оболочка предоставляет возможность выбора, вы можете перенаправить активацию на этот экземпляр или игнорировать её, если хотите.
public static class Program
{
// This example code shows how you could implement the required Main method to
// support multi-instance redirection. The minimum requirement is to call
// Application.Start with a new App object. Beyond that, you may delete the
// rest of the example code and replace it with your custom code if you wish.
static void Main(string[] args)
{
// First, we'll get our activation event args, which are typically richer
// than the incoming command-line args. We can use these in our app-defined
// logic for generating the key for this instance.
IActivatedEventArgs activatedArgs = AppInstance.GetActivatedEventArgs();
// If the Windows shell indicates a recommended instance, then
// the app can choose to redirect this activation to that instance instead.
if (AppInstance.RecommendedInstance != null)
{
AppInstance.RecommendedInstance.RedirectActivationTo();
}
else
{
// Define a key for this instance, based on some app-specific logic.
// If the key is always unique, then the app will never redirect.
// If the key is always non-unique, then the app will always redirect
// to the first instance. In practice, the app should produce a key
// that is sometimes unique and sometimes not, depending on its own needs.
string key = Guid.NewGuid().ToString(); // always unique.
//string key = "Some-App-Defined-Key"; // never unique.
var instance = AppInstance.FindOrRegisterInstanceForKey(key);
if (instance.IsCurrentInstance)
{
// If we successfully registered this instance, we can now just
// go ahead and do normal XAML initialization.
global::Windows.UI.Xaml.Application.Start((p) => new App());
}
else
{
// Some other instance has registered for this key, so we'll
// redirect this activation to that instance instead.
instance.RedirectActivationTo();
}
}
}
}
Main() — это первое, что запускается. Это выполняется до OnLaunched и OnActivated. Это позволяет определить, следует ли активировать этот или другой экземпляр перед выполнением любого другого кода инициализации в приложении.
Приведенный выше код определяет, активируется ли существующий или новый экземпляр приложения. Ключ используется для определения наличия существующего экземпляра, который требуется активировать. Например, если приложение можно запустить для обработки активации файлов, можно использовать имя файла в качестве ключа. Затем можно проверить, зарегистрирован ли экземпляр приложения с помощью этого ключа и активировать его вместо открытия нового экземпляра. Это идея кода: var instance = AppInstance.FindOrRegisterInstanceForKey(key);
Если обнаружен экземпляр, зарегистрированный с помощью ключа, активируется этот экземпляр. Если ключ не найден, текущий экземпляр (экземпляр, выполняющийся в настоящее время Main) создает объект приложения и запускается.
Фоновые задачи и многоуровневая настройка
- Внепроцессные фоновые задачи поддерживают многократное создание экземпляров. Как правило, каждый новый триггер приводит к новому экземпляру фоновой задачи (хотя технически говоря несколько фоновых задач может выполняться в одном и том же процессе узла). Тем не менее создается другой экземпляр фоновой задачи.
- Фоновые задачи в proc не поддерживают многоуровневую настройку.
- Фоновые звуковые задачи не поддерживают многоуровневую настройку.
- Когда приложение регистрирует фоновую задачу, обычно сначала проверяет, зарегистрирована ли задача, а затем удаляет и повторно регистрирует ее, или ничего не делает, чтобы сохранить существующую регистрацию. Это по-прежнему типичное поведение с многоэкземплярными приложениями. Однако приложение с мульти-инстанцированием может зарегистрировать другое название фоновой задачи для каждого экземпляра. Это приведет к множественным регистрациям одного и того же триггера, и при его срабатывании будет активировано несколько экземпляров фоновых задач.
- Службы приложений запускают отдельный экземпляр фоновой задачи службы приложений для каждого подключения. Это остается неизменным для приложений с несколькими экземплярами, то есть каждый экземпляр приложения с несколькими экземплярами получит собственный экземпляр фоновой задачи службы приложений.
Дополнительные рекомендации
- Поддержка многократной инстанциации обеспечивается приложениями UWP, предназначенными для проектов настольных приложений.
- Чтобы избежать проблем с состоянием гонки и конфликтами, приложения с несколькими экземплярами должны выполнить шаги по секционированием и синхронизации доступа к параметрам, локальному хранилищу приложений и любому другому ресурсу (например, файлам пользователей, хранилищу данных и т. д.), которые могут быть общими для нескольких экземпляров. Доступны стандартные механизмы синхронизации, такие как мьютексы, семафоры, события и т. д.
- Если файл Package.appxmanifest содержит
SupportsMultipleInstances, то расширения приложения не должны декларироватьSupportsMultipleInstances. - Если вы добавляете
SupportsMultipleInstancesв любое другое расширение, помимо фоновых задач или служб приложений, а приложение, на котором размещено расширение, также не объявляетSupportsMultipleInstancesв файле Package.appxmanifest, создается ошибка схемы. - Приложения могут использовать объявление ResourceGroup в манифесте для группировки нескольких фоновых задач в один хост. Это конфликтует с мульти-инстансированием, при котором каждая активация происходит на отдельном хосте. Поэтому приложение не может объявлять как
SupportsMultipleInstances, так иResourceGroupв манифесте.
Образец
См. пример перенаправления активации с несколькими экземплярами в разделе ,.
См. также
AppInstance.FindOrRegisterInstanceForKeyAppInstance.GetActivatedEventArgsAppInstance.RedirectActivationToОбработка активации приложения