Задержка приостановки приложения с помощью расширенного сеанса выполнения
В этой статье показано, как использовать расширенное выполнение для отложения при приостановке приложения, чтобы оно двигалось во время свернутого или под экраном блокировки.
Когда пользователь сворачивать или переключать приложение, оно помещается в приостановленное состояние. Его память сохраняется, но его код не выполняется. Это верно во всех выпусках ОС с визуальным пользовательским интерфейсом. Дополнительные сведения о приостановке приложения см. в разделе "Жизненный цикл приложений".
Существуют случаи, когда приложению может потребоваться продолжать работу, а не приостановлено, когда пользователь переходит от приложения или пока он свернут. Например, приложение подсчета шагов должно продолжать выполняться и отслеживать шаги, даже если пользователь переходит к использованию других приложений.
Если приложению необходимо продолжать работать, ос может продолжать работать или запрашивать выполнение. Например, при воспроизведении звука в фоновом режиме ОС может продолжать работу приложения, если выполнить эти действия для воспроизведения фонового носителя. В противном случае необходимо вручную запросить больше времени. Время выполнения фонового выполнения может занять несколько минут, но вы должны быть готовы к обработке сеанса, отозванного в любое время. Эти ограничения жизненного цикла приложения отключены, пока приложение работает под отладчиком. По этой причине важно проверить расширенное выполнение и другие средства для отсрочки приостановки приложений, не выполняясь под отладчиком или с помощью событий жизненного цикла, доступных в Visual Studio.
Создайте extendedExecutionSession, чтобы запросить больше времени для завершения операции в фоновом режиме. Тип создаваемого объекта ExtendedExecutionSession определяется параметром ExtendedExecutionReason, предоставляемым при его создании. Существует три значения перечисления ExtendedExecutionReason : Unspecified, LocationTracking и SavingData. В любое время можно запросить только один расширенный запрос ExtendedExecutionSession. Попытка создать другой сеанс, пока утвержденный запрос сеанса в настоящее время активен, приведет к возникновению исключения 0x8007139F из конструктора ExtendedExecutionSession, указывающего, что группа или ресурс не находится в правильном состоянии для выполнения запрошенной операции. Не используйте ExtendedExecutionForegroundSession и ExtendedExecutionForegroundReason; они требуют ограниченных возможностей и недоступны для использования в приложениях Store.
Выполнение во время свернутого
Существует два случая, когда можно использовать расширенное выполнение:
- В любой момент во время регулярного выполнения переднего плана, а приложение находится в состоянии выполнения.
- После того как приложение получило событие приостановки (ОС будет перемещено в приостановленное состояние) в обработчике событий приостановки приложения.
Код для этих двух случаев одинаков, но приложение ведет себя немного по-разному. В первом случае приложение остается в состоянии выполнения, даже если событие, которое обычно активирует приостановку (например, пользователь перемещается от приложения). Приложение никогда не получит событие приостановки, пока расширение выполнения действует. Когда расширение удаляется, приложение снова становится доступным для приостановки.
Во втором случае, если приложение переходит в приостановленное состояние, оно останется в состоянии приостановки в течение периода расширения. После истечения срока действия расширения приложение вводит приостановленное состояние без дальнейшего уведомления.
Используйте ExtendedExecutionReason.Unspecified при создании extendedExecutionSession , чтобы запросить дополнительное время, прежде чем приложение перейдет в фон для таких сценариев, как обработка мультимедиа, компиляция проекта или сохранение сетевого подключения. На настольных устройствах под управлением Windows 10 для классических выпусков (Home, Pro, Enterprise и Education) это подход, используемый, если приложению необходимо избежать приостановки, пока она свернута.
Запросите расширение при запуске длительной операции, чтобы отложить переход состояния приостановки , который в противном случае возникает при переходе приложения в фон. На настольных устройствах расширенные сеансы выполнения, созданные с помощью ExtendedExecutionReason.Unspecified , имеют ограничение времени, поддерживающего батарею. Если устройство подключено к мощности стены, ограничение на длину расширенного периода выполнения не ограничено. Если устройство находится на заряде батареи, расширенный период выполнения может выполняться до десяти минут в фоновом режиме.
Пользователь планшета или ноутбука может получить то же длительное поведение, за счет жизненной батареи, когда приложение может выполнять фоновые задачи в разделе "Использование батареи" по параметрам приложения . (Чтобы найти этот параметр на ноутбуке, перейдите на страницу >>Параметры использования батареи>системы по приложению (ссылка на процент оставшейся батареи) > выберите приложение, которое отключает управляемое Windows>, выберите разрешить приложению > выполнять фоновые задачи.
Во всех выпусках ОС этот вид расширенного сеанса выполнения останавливается при входе устройства в подключенный резервный режим. На мобильных устройствах под управлением Windows 10 Mobile этот вид расширенного сеанса выполнения будет выполняться до тех пор, пока экран находится на экране. При отключении экрана устройство немедленно пытается войти в режим ожидания с низкой мощностью. На настольных устройствах сеанс продолжится, если появится экран блокировки. Устройство не вводит подключенный резервный режим в течение определенного периода времени после отключения экрана. В выпуске Xbox OS устройство введет режим ожидания через один час, если пользователь не изменяет значение по умолчанию.
Отслеживание расположения пользователя
Укажите ExtendedExecutionReason.LocationTracking при создании extendedExecutionSession , если ваше приложение должно регулярно регистрировать расположение из GeoLocator. Приложения для отслеживания фитнеса и навигации, которые должны регулярно отслеживать расположение пользователя и использовать эту причину.
Расширенный сеанс выполнения отслеживания расположения может выполняться до тех пор, пока экран заблокирован на мобильном устройстве. Однако на устройство может выполняться только один такой сеанс. Расширенный сеанс выполнения отслеживания расположения можно запросить только на переднем плане, и приложение должно находиться в состоянии "Выполнение ". Это гарантирует, что пользователь знает, что приложение инициировало сеанс расширенного отслеживания расположения. Геолокатор по-прежнему можно использовать, пока приложение находится в фоновом режиме с помощью фоновой задачи или службы приложений, не запрашивая расширенный сеанс выполнения отслеживания расположения.
Сохранение критически важных данных локально
Укажите ExtendedExecutionReason.SaveData при создании extendedExecutionSession для сохранения пользовательских данных в случае, если не сохранять данные перед завершением приложения приведет к потере данных и отрицательному интерфейсу пользователя.
Не используйте этот вид сеанса, чтобы продлить время существования приложения для отправки или скачивания данных. Если необходимо передать данные, запросите фоновую передачу или зарегистрируйте службу MaintenanceTrigger для обработки передачи при доступности питания AC. Расширенный сеанс выполнения ExtendedExecutionReason.SavingData можно запрашивать, если приложение находится на переднем плане и в состоянии "Выполнение", либо в фоновом режиме и в состоянии приостановки.
Состояние приостановки — это последняя возможность во время жизненного цикла приложения, которую приложение может выполнить до завершения работы приложения. ExtendedExecutionReason.SavingData — единственный тип ExtendedExecutionSession , который можно запросить в состоянии приостановки . Запрос расширенного сеанса выполнения ExtendedExecutionReason.SavingData , когда приложение находится в состоянии приостановки , создает потенциальную проблему, о которую следует знать. Если расширенный сеанс выполнения запрашивается в состоянии приостановки , а пользователь снова запрашивает запуск приложения, может занять много времени. Это связано с тем, что период времени сеанса расширенного выполнения должен завершиться до закрытия старого экземпляра приложения и запуска нового экземпляра приложения. Время запуска производительности пожертвовано, чтобы гарантировать, что состояние пользователя не потеряно.
Запрос, удаление и отзыв
Существует три основных взаимодействия с расширенным сеансом выполнения: запрос, удаление и отзыв. Создание запроса моделировается в следующем фрагменте кода.
Запросить
var newSession = new ExtendedExecutionSession();
newSession.Reason = ExtendedExecutionReason.Unspecified;
newSession.Revoked += SessionRevoked;
ExtendedExecutionResult result = await newSession.RequestExtensionAsync();
switch (result)
{
case ExtendedExecutionResult.Allowed:
DoLongRunningWork();
break;
default:
case ExtendedExecutionResult.Denied:
DoShortRunningWork();
break;
}
Вызов RequestExtensionAsync проверяет операционную систему, чтобы узнать, утверждено ли пользователем фоновое действие для приложения и есть ли у системы доступные ресурсы для включения фонового выполнения. Только один сеанс будет утвержден для приложения в любое время, что приведет к отказу в сеансе дополнительных вызовов RequestExtensionAsync .
Вы можете заранее проверить BackgroundExecutionManager , чтобы определить BackgroundAccessStatus, который является параметром пользователя, который указывает, может ли ваше приложение работать в фоновом режиме или нет. Дополнительные сведения об этих параметрах пользователя см. в разделе "Фоновая активность" и "Осведомленность о энергии".
ExtendedExecutionReason указывает, что операция, выполняемая приложением в фоновом режиме. Строка описания — это читаемая пользователем строка, которая объясняет, почему приложение должно выполнять операцию. Эта строка не представлена пользователю, но может быть доступна в будущем выпуске Windows. Обработчик отозванных событий требуется, чтобы расширенный сеанс выполнения был корректно остановлен, если пользователь или система решит, что приложение больше не может работать в фоновом режиме.
Отозвано
Если у приложения есть активный расширенный сеанс выполнения, и системе требуется фоновое действие, чтобы остановиться, так как для приложения переднего плана требуются ресурсы, сеанс отменяется. Расширенный период времени сеанса выполнения никогда не завершается без первого запуска обработчика отозванных событий.
Когда событие "Отозвано" запускается для расширенного сеанса выполнения ExtendedExecutionReason.SavingData, приложение имеет одну секунду для завершения операции, выполняемой и завершения приостановки.
Отмена может возникать по многим причинам: достигнуто ограничение времени выполнения, достигнута квота фоновой энергии или память должна быть восстановлена, чтобы пользователь открыл новое приложение на переднем плане.
Ниже приведен пример обработчика отозванных событий:
private async void SessionRevoked(object sender, ExtendedExecutionRevokedEventArgs args)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
switch (args.Reason)
{
case ExtendedExecutionRevokedReason.Resumed:
rootPage.NotifyUser("Extended execution revoked due to returning to foreground.", NotifyType.StatusMessage);
break;
case ExtendedExecutionRevokedReason.SystemPolicy:
rootPage.NotifyUser("Extended execution revoked due to system policy.", NotifyType.StatusMessage);
break;
}
EndExtendedExecution();
});
}
Утилизация
Последним шагом является удаление расширенного сеанса выполнения. Вы хотите удалить сеанс и любые другие ресурсы с интенсивным объемом памяти, так как в противном случае энергия, используемая приложением во время ожидания закрытия сеанса, будет считаться в соответствии с квотой энергии приложения. Чтобы сохранить как можно больше энергии для приложения, важно удалить сеанс, когда вы закончите работу с сеансом, чтобы приложение двигалось в приостановленное состояние быстрее.
Удаление сеанса самостоятельно, а не ожидание события отзыва, уменьшает потребление энергетических квот вашего приложения. Это означает, что ваше приложение будет разрешено работать в фоновом режиме дольше в будущих сеансах, так как вы будете иметь больше квоты на энергию для этого. До конца операции необходимо сохранить ссылку на объект ExtendedExecutionSession , чтобы можно было вызвать его метод Dispose .
Фрагмент кода, который удаляет расширенный сеанс выполнения, следует:
void ClearExtendedExecution(ExtendedExecutionSession session)
{
if (session != null)
{
session.Revoked -= SessionRevoked;
session.Dispose();
session = null;
}
}
Приложение может одновременно использовать только один параметр ExtendedExecutionSession . Многие приложения используют асинхронные задачи для выполнения сложных операций, требующих доступа к ресурсам, таким как хранилище, сеть или сетевые службы. Если операция требует выполнения нескольких асинхронных задач, необходимо учитывать состояние каждой из этих задач перед удалением ExtendedExecutionSession и разрешением приостановки приложения. Для этого требуется подсчет количества задач, которые по-прежнему выполняются, и не удаляет сеанс, пока это значение не достигнет нуля.
Ниже приведен пример кода для управления несколькими задачами в течение расширенного периода сеанса выполнения. Дополнительные сведения о том, как использовать это в приложении, см. в следующем примере кода:
static class ExtendedExecutionHelper
{
private static ExtendedExecutionSession session = null;
private static int taskCount = 0;
public static bool IsRunning
{
get
{
if (session != null)
{
return true;
}
else
{
return false;
}
}
}
public static async Task<ExtendedExecutionResult> RequestSessionAsync(ExtendedExecutionReason reason, TypedEventHandler<object, ExtendedExecutionRevokedEventArgs> revoked, String description)
{
// The previous Extended Execution must be closed before a new one can be requested.
ClearSession();
var newSession = new ExtendedExecutionSession();
newSession.Reason = reason;
newSession.Description = description;
newSession.Revoked += SessionRevoked;
// Add a revoked handler provided by the app in order to clean up an operation that had to be halted prematurely
if(revoked != null)
{
newSession.Revoked += revoked;
}
ExtendedExecutionResult result = await newSession.RequestExtensionAsync();
switch (result)
{
case ExtendedExecutionResult.Allowed:
session = newSession;
break;
default:
case ExtendedExecutionResult.Denied:
newSession.Dispose();
break;
}
return result;
}
public static void ClearSession()
{
if (session != null)
{
session.Dispose();
session = null;
}
taskCount = 0;
}
public static Deferral GetExecutionDeferral()
{
if (session == null)
{
throw new InvalidOperationException("No extended execution session is active");
}
taskCount++;
return new Deferral(OnTaskCompleted);
}
private static void OnTaskCompleted()
{
if (taskCount > 0)
{
taskCount--;
}
//If there are no more running tasks than end the extended lifetime by clearing the session
if (taskCount == 0 && session != null)
{
ClearSession();
}
}
private static void SessionRevoked(object sender, ExtendedExecutionRevokedEventArgs args)
{
//The session has been prematurely revoked due to system constraints, ensure the session is disposed
if (session != null)
{
session.Dispose();
session = null;
}
taskCount = 0;
}
}
Убедитесь, что приложение хорошо использует ресурсы
Настройка памяти и энергопотребления приложения — это ключ к обеспечению того, что операционная система позволит приложению продолжать работать, когда оно больше не является приложением переднего плана. Используйте API управления памятью, чтобы узнать, сколько памяти использует приложение. Чем больше памяти использует ваше приложение, тем сложнее, чтобы операционная система сохраняла работу приложения, когда другое приложение находится на переднем плане. Пользователь в конечном счете контролирует все фоновые действия, которые ваше приложение может выполнять и имеет видимость о влиянии вашего приложения на использование батареи.
Используйте BackgroundExecutionManager.RequestAccessAsync , чтобы определить, должен ли пользователь решить, что фоновая активность приложения должна быть ограничена. Помните об использовании батареи и запустите его только в фоновом режиме, если необходимо выполнить действие, которое пользователь хочет.
См. также
Пример расширенного выполнения
Жизненный цикл приложения
Жизненный цикл приложений. Сохранение активности приложений с помощью фоновых задач и расширенного управления фоновой памятью выполнения
Фоновые передачи
Осведомленность о батарее и фоновое действие
Класс MemoryManager
Воспроизведение мультимедиа в фоновом режиме