tmytのらくがき

個人の日記レベルです

ExtendedExecutionSessionでサスペンド延長中にリジュームしたときちゃんと面倒みないと運が悪いとアプリが死ぬ話

UWPでOnSuspendingでファイルを保存するとかどうしても長いことかかることをしたいときにExtendedExecutionSessionというのでサスペンド時間を延長できます。結構便利なので頭の隅に置いておくといいと思います。

で、表題の件ですが、ExtendedExecutionSessionでサスペンド時間を延長して、その中でながーーーい処理をしているときにアプリがリジュームしてきて、さらにExtendedExecutionSessionのRevokedイベントで何もせず、ずっと長い処理を実行し続けて15秒ぐらい経過するとOnResumeに失敗してアプリが死にます。

ちゃんとまとめます。

  • ExtendedExecutionSessionを使ってる
  • OnSuspendで長いことかかるかもしれないことをやってる
  • ExtendedExecutionSession.RevokedとかこないでしょHAHAHAとか思ってる

なぜなのか

GetDeferralしてからCompleteするまではOnResumeの実行がブロックされる。ようです。まぁいわれてみればその通りなんですが…。

どーすんの

OnResumeが来たときExtendedExecutionSessionのRevokedイベントが呼ばれます。なのでちゃんとOnResumeは検出できるわけです。 つまり、ここでいったんdeferralを終了してあげるとブロックされていたResume処理が実行されるのでアプリがりじゅーむできずに死ぬことはなくなります。が、サスペンド処理は適当にいい感じにする必要はあります。

こんなん

とりあえずこういう感じで実装してそれなりに動いているようですが、これでいいのかよ感はあります。

var completed = false;

extendedSession = new ExtendedExecutionSession();
extendedSession.Reason = ExtendedExecutionReason.SavingData;
extendedSession.Revoked = (o, args) =>
{
    lock (this)
    {
        if (completed) return;
        completed = true;
    }
    deferral.Complete();
    extendedSession?.Dispose();
    extendedSession = null;
});