没有UI问题或任何一个很好的洞察力。你的代码有效。你的期望是错误的。
使用你告诉你的应用程序,你需要时间来保存,它不会被撤销,直到你完成。在你的情况下,大约需要9秒。
尝试挂起应用程序,等待10秒钟然后撤销它。它会立即发生。 然后尝试暂停应用程序并在会话完成之前撤消它。现在会告诉你的操作系统,你的应用程序不能被撤销,它必须等到保存过程完成。那就是你想要的。
见Microsoft doc on extended execution:
请求一个ExtendedExecutionReason.SavingData
扩展执行会话,而应用程序是在悬浮状态创建你应该知道的一个潜在的问题。如果在挂起状态下请求扩展执行会话,并且用户请求应用程序再次启动,则可能需要很长时间才能启动。这是因为扩展执行会话时间段必须在应用程序的旧实例关闭并且可以启动应用程序的新实例之前完成。牺牲启动性能时间是为了保证用户状态不会丢失。
什么在关于“撤销”一节提到的是对你有意思,太:
当Revoked
事件为ExtendedExecutionReason.SavingData
扩展执行会议解雇,该应用程序有一秒钟完成操作它正在执行并完成暂停。
一秒钟是不够的完成你的9秒钟等待。
为了消除延迟显示调试输出的可能性,您可以通过将当前时间添加到输出来对其进行测试。 操作系统可能在会话未正常关闭时出现问题,因为9秒未完成。
还应注意EnterBackground的一句话:
此前的悬浮回调是保存状态后,用户与您的应用程序完成了会议的最佳场所。但是,现在应用程序可能会继续在后台运行,然后由于触发器活动而回到前台而没有达到暂停状态。用户会话之后保存数据的最佳位置是在您输入的后台事件处理程序中。
如果Exiting
事件被触发,您可能会想要执行您的代码。
对于OnSuspending
尝试在撤销发生时立即使用for循环进行等待(取消保存进程),一次只等待半秒钟。
UPDATE:
...或者使用Background Task为暂停似乎是结束前的唯一可靠的警告:
//
// 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();
}
UPDATE2:
对于 “适当”应该怎么办,请看official example:
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;
});
}
似乎你不会错过任何东西,但是在文档中找不到任何地方提到“应该在恢复应用程序时触发撤销的事件”。也许你需要在OnResuming中添加一些额外的代码。 –
@MehrzadChehraz否 - 恢复事件似乎只在暂停事件结束后才会被触发。这意味着在发布模式下,由于时间限制,应用程序将被操作系统杀死,并且根本不会升级和恢复事件。 – Romasz
是的你是对的。顺便说一句,你可以添加一个链接或文件说:“恢复应用程序时应该被解雇的事件”? –