Нет никаких проблем с пользовательским интерфейсом или что-то в этом роде. Ваш код работает. Ваше ожидание ошибочно.
Используя ExtendedExecutionSession
, вы сообщаете своему приложению, что вам нужно время для сохранения, и оно не будет отозвано, пока вы не закончите. В вашем случае это занимает около 9 секунд.
Попробуйте приостановить приложение, подождите 10 секунд, а затем отзовите его. Это произойдет немедленно. Затем попробуйте приостановить приложение и отозвать его до завершения сеанса. Теперь ExtendedExecutionSession
сообщит вашей ОС, что ваше приложение еще не может быть отозвано, и оно должно дождаться завершения процесса сохранения. Это то, что ты хочешь.
См. документ Microsoft при расширенном выполнении:
Запрос расширенного сеанса выполнения ExtendedExecutionReason.SavingData
, когда приложение находится в состоянии «Приостановка», создает потенциальную проблему, о которой вам следует знать. Если расширенный сеанс выполнения запрашивается в состоянии «Приостановка», а пользователь запрашивает повторный запуск приложения, может показаться, что запуск занимает много времени. Это связано с тем, что период времени расширенного сеанса выполнения должен завершиться до закрытия старого экземпляра приложения и запуска нового экземпляра приложения. Время запуска приносится в жертву, чтобы гарантировать, что пользовательское состояние не будет потеряно.
То, что сказано в разделе про "Revoke", вам тоже интересно:
Когда событие Revoked
запускается для расширенного сеанса выполнения ExtendedExecutionReason.SavingData
, у приложения есть одна секунда, чтобы завершить операцию, которую оно выполняло, и завершить приостановку.
Одной секунды недостаточно, чтобы закончить 9-секундное ожидание.
Чтобы исключить возможность отложенного отображения вашего отладочного вывода, вы можете протестировать его, добавив в вывод текущее время. У ОС, вероятно, есть проблема с тем, что сеанс не закрывается должным образом, потому что 9 секунд не заканчиваются.
Также обратите внимание на примечание к EnterBackground. :
Ранее приостановка обратного вызова была лучшим местом для сохранения состояния после того, как пользователь завершил сеанс работы с вашим приложением. Однако теперь приложение может продолжить работу в фоновом режиме, а затем вернуться на передний план из-за активности триггера, даже не достигнув состояния приостановки. Лучшее место для сохранения данных после сеанса пользователя — во введенном вами обработчике фоновых событий.
Вы, вероятно, захотите сделать свой код на случай, если будет запущено событие Exiting
.
Для OnSuspending
попробуйте выполнить ожидание с циклом for, который прерывается (отменяет процесс сохранения), как только происходит отзыв, ожидая только полсекунды за раз.
ОБНОВИТЬ:
...Или используйте фоновую задачу, так как надежное предупреждение перед завершением:
//
// Declare that your background task's Run method makes asynchronous calls by
// using the async keyword.
//
public async void Run(IBackgroundTaskInstance taskInstance)
{
//
// Create the deferral by requesting it from the task instance.
//
BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
//
// Call asynchronous method(s) using the await keyword.
//
var result = await ExampleMethodAsync();
//
// Once the asynchronous method(s) are done, close the deferral.
//
deferral.Complete();
}
ОБНОВЛЕНИЕ 2:
Чтобы узнать, как это сделать правильно, см. официальный пример:
private async void OnSuspending(object sender, SuspendingEventArgs args)
{
suspendDeferral = args.SuspendingOperation.GetDeferral();
rootPage.NotifyUser("", NotifyType.StatusMessage);
using (var session = new ExtendedExecutionSession())
{
session.Reason = ExtendedExecutionReason.SavingData;
session.Description = "Pretending to save data to slow storage.";
session.Revoked += ExtendedExecutionSessionRevoked;
ExtendedExecutionResult result = await session.RequestExtensionAsync();
switch (result)
{
case ExtendedExecutionResult.Allowed:
// We can perform a longer save operation (e.g., upload to the cloud).
try
{
MainPage.DisplayToast("Performing a long save operation.");
cancellationTokenSource = new CancellationTokenSource();
await Task.Delay(TimeSpan.FromSeconds(10), cancellationTokenSource.Token);
MainPage.DisplayToast("Still saving.");
await Task.Delay(TimeSpan.FromSeconds(10), cancellationTokenSource.Token);
MainPage.DisplayToast("Long save complete.");
}
catch (TaskCanceledException) { }
break;
default:
case ExtendedExecutionResult.Denied:
// We must perform a fast save operation.
MainPage.DisplayToast("Performing a fast save operation.");
await Task.Delay(TimeSpan.FromSeconds(1));
MainPage.DisplayToast("Fast save complete.");
break;
}
session.Revoked -= ExtendedExecutionSessionRevoked;
}
suspendDeferral?.Complete();
suspendDeferral = null;
}
private async void ExtendedExecutionSessionRevoked(object sender, ExtendedExecutionRevokedEventArgs args)
{
//If session is revoked, make the OnSuspending event handler stop or the application will be terminated
if (cancellationTokenSource != null){ cancellationTokenSource.Cancel(); }
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
switch (args.Reason)
{
case ExtendedExecutionRevokedReason.Resumed:
// A resumed app has returned to the foreground
rootPage.NotifyUser("Extended execution revoked due to returning to foreground.", NotifyType.StatusMessage);
break;
case ExtendedExecutionRevokedReason.SystemPolicy:
//An app can be in the foreground or background when a revocation due to system policy occurs
MainPage.DisplayToast("Extended execution revoked due to system policy.");
rootPage.NotifyUser("Extended execution revoked due to system policy.", NotifyType.StatusMessage);
break;
}
suspendDeferral?.Complete();
suspendDeferral = null;
});
}
person
Neepsnikeep
schedule
10.08.2017
Suspending
до тех пор, пока все не будет сделано. Сможете ли вы завершить, как только получите расширенное выполнение (перед выполнением ожидания)? - person Peter Torr - MSFT   schedule 30.03.2016