扩展执行无法正常工作?

时间:2016-03-19 19:13:16

标签: c# win-universal-app windows-10-mobile

我无法让ExtendedExecution正常工作。问题是在执行完成之前不会触发Revoked事件。如果我们采样:

private async void OnSuspending(object sender, SuspendingEventArgs e)
{
    Debug.WriteLine("Suspending in app");
    var deferral = e.SuspendingOperation.GetDeferral();
    using (var session = new ExtendedExecutionSession())
    {
        session.Reason = ExtendedExecutionReason.SavingData;
        session.Description = "Upload Data";
        session.Revoked += (s, a) => { Debug.WriteLine($"Extended execution revoked because of {a.Reason}"); };
        var result = await session.RequestExtensionAsync();
        if (result == ExtendedExecutionResult.Denied) Debug.WriteLine("Extended execution failed");
        else
        {
            Debug.WriteLine("Executing");
            await Task.Run(() => { Task.Delay(9000).Wait(); Debug.WriteLine("Finished the task"); });
            Debug.WriteLine("Executing finished");
        }
        Debug.WriteLine("Suspending after execution");
    }
    deferral.Complete();
}

文档说明在恢复应用程序时应该触发Revoked事件,但是如果您尝试附加调试器的代码,那么您将看到调试输出看起来没问题,但您必须等待9000毫秒它出现了。这意味着代码将暂停,直到会话结束。

最大的问题是,如果你在没有连接调试器的情况下启动它,启动应用程序,暂停然后恢复,你会看到黑屏几秒钟,然后操作系统将终止你的应用程序。

我错过了什么吗?有没有人让它正常工作?

2 个答案:

答案 0 :(得分:1)

awaitTask的使用导致您的继续任务保留在主线程上,因此您必须等待黑屏。 请记住,await行为是将执行安排到Dispatcher,而不是开始新线程,NOR将其执行安排到ThreadPool中。因此,在Delay()结束之前,不能再处理任何UI消息。

只需在新线程上执行耗时的操作,但确保会话保持打开状态直到结束。

看一下这个https://msdn.microsoft.com/en-us/magazine/jj991977.aspx,以便更好地了解执行的执行方式

答案 1 :(得分:1)

没有UI问题或任何问题。你的代码有效。你的期望是错误的。

使用COLLSCAN告诉您的应用,您需要时间保存,并且在完成之前不会撤销。在你的情况下大约需要9秒。

尝试暂停应用,等待10秒然后撤消它。它会立即发生。 然后尝试暂停应用程序并在会话结束前撤消它。现在ExtendedExecutionSession将告诉您的操作系统您的应用程序尚未被撤销,并且必须等到保存过程完成。这就是你想要的。

请参阅Microsoft doc on extended execution

  

在应用处于暂停状态时请求ExtendedExecutionSession延长执行会话会产生您应该注意的潜在问题。如果在Suspending状态下请求扩展执行会话,并且用户请求再次启动应用程序,则可能需要很长时间才能启动。这是因为扩展的执行会话时间段必须在关闭旧应用程序实例并启动应用程序的新实例之前完成。牺牲启动性能时间以保证用户状态不会丢失。

关于“撤销”部分中提到的内容对您而言也很有趣:

  

ExtendedExecutionReason.SavingData延长执行会话触发Revoked事件时,应用程序有一秒钟完成正在执行的操作并完成暂停。

一秒钟还不足以完成9秒等待。

为了消除延迟显示调试输出的可能性,您可以通过将当前时间添加到输出来进行测试。 操作系统可能存在会话未正确关闭的问题,因为9秒没有完成。

另请注意EnterBackground上的评论:

  

以前,在用户完成与您的应用的会话后,您的暂停回拨是保存状态的最佳位置。但是,现在应用程序可以继续在后台运行,然后由于触发器活动而返回到前台,而不会达到挂起状态。用户会话在输入的后台事件处理程序中保存数据的最佳位置。

如果ExtendedExecutionReason.SavingData事件被触发,您可能希望执行代码。

对于Exiting尝试在撤销发生时立即执行等待for循环(取消保存过程),等待一次只有半秒。

更新:

...或使用Background Task,因为暂停似乎是终止前唯一可靠的警告:

OnSuspending

<强> UPDATE2

对于“正确”的方式,请参阅official example

//
// 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();
}