Tombstoned(トゥームストーン)とDormant(ドーマント)について

Windows Phoneではアプリケーションが1つしか動かないので、アプリケーションの実行中にLauncherやChooserを呼び出したり、スタートボタンを押して最初の画面に戻ったりして別のアプリケーションを起動すると、実行していたアプリケーションは休止状態になり、その時点でアプリケーションのインスタンスは破棄されます。

ここでいう休止状態とはまたもとの状態に戻れる状態のことです。例えば、アプリケーションの実行→スタートボタンを押す→戻るボタンを押す、の順に操作するとちゃんと元のアプリケーションの状態に戻るはずです。これはアプリケーションの開発者がアプリケーションで発生するActivate、Deactivateイベントや各ページのOnNavigatedToとOnNavigatedFromメソッドをオーバーライドすることで、休止状態のアプリケーションを元の状態に復元することで実現しています。

具体的には、以下のようなことをします。

Deactivateイベント アプリケーションの状態を保存
Activateイベント 休止前のアプリケーションの状態を復元
OnNavigatedFrom 直前に表示していたページの情報を保存
OnNavigatedTo 直前に表示していたページの情報を復元


休止状態のアプリケーションを確認したければ戻るボタンを長押し(Fast Application Switching)することで確認することができます。最大で5つまで休止状態のアプリケーションはストックされます。ただしFast Application Switchingの機能はMangoからしか搭載されていません。

タイトルにあるTombstonedとDormantはどちらも休止状態のことです。つまり休止状態には2つの状態が存在することになります。

それぞれの単語を辞書で引くと、Dormantは「休眠」、Tombstoneは「墓石」と出てきます。つまりDormantは休んでいる状態で、Tombstonedは死んでいる状態です。この違いは開発者にとっては重要な違いです。それぞれの違いは次の通りです。

Dormant アプリケーションが中断する直前の状態をそのままメモリ上に保存します。そのため高速にアプリケーションは復元されます。また、開発者は特になにもする必要がありません。
Tombstoned 基本的にはDeactivateイベントとOnNavigatedFromでStateに保存した情報しか持っていません。OSが行ってくれるのはアプリケーションのインスタンスを立ち上げと以前表示していたページの表示までで、以前のアプリケーションの状態までは復元してくれないので、その部分は開発者が保存した情報をもとに復元しなければなりません。

もちろんすべての休止状態がDormantであれば開発者はなにをする必要がありませんが、Dormantの状態はメモリを消費するのですべてのアプリケーションをDormantにすることはできません。例えばメモリを大量に消費するようなアプリケーションを実行するときには、Dormantの状態のアプリケーションが確保しているメモリのせいで実行しているアプリケーションに影響を与えかねません。それではUXが損なわれるので使わなくなったものから順にTombstonedへと移行しメモリを解放します。

この2つの休止状態はFast Application Switchingで確認してもどちらの状態にあるのか分からないので視覚的に確認することはできません。ただし、開発者であれば自分の作成したアプリケーションがどちらの状態から復元してきたのかを知ることができます。

アプリケーションを復元するときは開発者はどちらの状態なのかを判断してアプリケーションを作成する必要があります。なぜならDormantのときは復元する必要がないからです。

そこでDormantかTombstonedかを判断する方法があります。それがApp.xaml.csで実装されているActivatedイベントのActivatedEventArgsのIsApplicationInstancePreservedプロパティです。このフラグがtrueのときはDormant、そうでなければTombstonedです。

private void Application_Activated(object sender, ActivatedEventArgs e)
{
    if (e.IsApplicationInstancePreserved)
    {
        // Dormant
    }
    else
    {
        // Tombstoned
    }
}

ただし開発中にこれをそのまま実行するとほぼIsApplicationInstancePreservedがtrueで返ってきます。それも当然でOSのメモリが空いている状態では必ずDormant状態に移行するからです。そこでデバッグ用に強制的にTombstonedに移行するように設定することができます。

プロジェクト → プロパティ → デバッグに「デバッグ中の非アクティブ化時に破棄する」という難しい文言がありますが、これにチェックを入れるとデバッグ実行時には必ずTombstonedの状態になります。

7.0まではDormantの状態がなかったのでこのようなことを考慮する必要がなかったのですが、7.1からDormantという状態が組み込まれたことによってユーザーにとってはとても喜ばしい機能が追加されたことになりますが、そのために開発者はそれに向けて対応が必要になります。

少しおおげさに書いたかもしれませんがコードをみれば対応自体はとても簡単です。7.0で作成されたアプリケーションはDormant状態に移行しないのでかならず復元が必要になりますが、7.1ではDormantによる高速にアプリケーションの復元が行えるというメリットがあります。

もしこれからアプリケーションを作成される方は7.1で作成するアプリケーションは単純にAPIが増えるだけでなく、それ以外にもDormantとうい高速にアプリケーションを復元できるメリットがあることも考慮したほうがよいです。

参考:Execution Model Overview for Windows Phone