首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Windows 8 應用生命週期管理精要:掛起、恢復、終止的狀態機與最佳實踐

     編輯:關於.NET

前言:系統掌控生命週期,應用負責狀態持久化

Windows 8 引入全新應用生命週期模型:**使用者不再手動關閉應用**,系統根據資源壓力 (記憶體、CPU、電池) 自動 **掛起** 背景應用,必要時 **終止** 以釋放資源。開發者必須正確處理 `Suspending` (5 秒存檔)、`Resuming` (還原 UI)、`Activated` (啟動/從終止恢復) 三大事件,確保使用者感覺應用「永遠在運行」。

一、生命週期狀態機與事件流

生命週期狀態圖

事件流程

核心狀態轉換

狀態觸發條件系統動作應用必做
Running (執行中)使用者啟動/切換至應用發送 `Activated` 事件 (`Kind=Launch` 或 `Kind=Switch`)`OnLaunched` 初始化 / `OnActivated` 恢復導航狀態
Suspending (掛起中)使用者切換離開 (Win+Tab, Start, 其他應用)發送 `Suspending` 事件,**5 秒內必須完成** (超時即終止)**序列化所有暫態狀態** (導航堆疊、表單輸入、暫存資料) 至 `ApplicationData.LocalSettings/Folder`;釋放獨佔資源 (檔案控制代碼、網路連線、感測器、媒體引擎)。
Suspended (已掛起)掛起完成進程保留在記憶體,**凍結所有執行緒**,不消耗 CPU/磁碟/網路無程式碼執行
Resuming (恢復中)使用者切回應用 (從掛起狀態)發送 `Resuming` 事件,進程解凍,變數/記憶體狀態完整保留**刷新可能過期的 UI** (新聞列表、即時資料、地理位置、Token 續期);**無需重新載入已序列化狀態** (記憶體尚在)。
Terminated (已終止)系統記憶體不足 / 使用者關閉應用 (下拉關閉) / 系統關機 / 應用崩潰**無任何事件通知**,進程直接殺掉,記憶體釋放**下次啟動時** (`Activated` -> `OnLaunched` `PreviousExecutionState == Terminated`) **從本地儲存還原完整狀態**。

多應用切換時序圖

啟用App1

啟用App2_App1掛起

啟用App3_App2掛起

繼續切換

記憶體不足_App1終止

切回App2_恢復

二、關鍵事件實作細節

1. Activated 事件與 OnLaunched/OnActivated 多載


// App.xaml.cs
protected override void OnLaunched(LaunchActivatedEventArgs args) {
    // args.PreviousExecutionState: NotRunning, Running, Suspended, Terminated, ClosedByUser
    if (args.PreviousExecutionState == ApplicationExecutionState.Terminated) {
        // 從終止恢復:載入儲存的 SessionState
        await RestoreSessionStateAsync();
    } else if (args.PreviousExecutionState == ApplicationExecutionState.Suspended) {
        // 從掛起恢復:記憶體完整,僅需刷新 UI
        RefreshUI();
    } else {
        // 冷啟動
        InitializeApp();
    }
    // 通用導航邏輯
    if (rootFrame.Content == null) rootFrame.Navigate(typeof(MainPage), args.Arguments);
    Window.Current.Activate();
}

protected override void OnActivated(IActivatedEventArgs args) {
    // 處理非啟動激活:Search, Share, File, Protocol, Toast, Contact 等
    if (args.Kind == ActivationKind.Search) { /* ... */ }
    // 確保視窗啟動
    Window.Current.Activate();
}

2. Suspending 事件:5 秒存檔黃金法則


private async void OnSuspending(object sender, SuspendingEventArgs e) {
    var deferral = e.SuspendingOperation.GetDeferral(); // 非同步存檔必須取得 Deferral
    try {
        // 1. 儲存導航狀態 (Frame.GetNavigationState)
        // 2. 儲存頁面級暫態資料 (實作 ISuspendable 接口的頁面自行存檔)
        // 3. 儲存應用級設定/暫存資料
        await SaveSessionStateAsync(); 
        
        // 4. 釋放獨佔資源
        ReleaseExclusiveResources();
    } finally {
        deferral.Complete(); // 必須調用,否則系統視為超時而終止
    }
}

3. Resuming 事件:輕量級 UI 刷新


private void OnResuming(object sender, object e) {
    // 記憶體完整,ViewModel 狀態仍在
    // 僅刷新可能過期的資料:新聞、即時股價、地理位置、OAuth Token
    foreach (var page in GetActivePages()) {
        if (page is IRefreshable) ((IRefreshable)page).RefreshData();
    }
}

三、SessionState 序列化最佳實踐

SuspensionManager 輔助類別 (標準範本內建)

  • 自動處理 `Frame` 導航堆疊序列化/反序列化 (`SessionState["FrameState"]`)。
  • 提供 `SaveAsync()` / `RestoreAsync()` 封裝 `ApplicationData.Current.LocalFolder` 讀寫。
  • 頁面實作 `SaveState(Dictionary state)` / `LoadState(Object navigationParameter, Dictionary state)` 介面,由 `SuspensionManager` 自動調用。

儲存容量與效能

  • `LocalSettings`:適合小型鍵值對 (≤ 8KB/值,總計 ≤ 1MB),即時同步。
  • `LocalFolder`:適合大型物件序列化 (JSON/XML/二進位)、資料庫檔案,**無大小限制** (受磁碟配額限制),非同步 I/O。
  • **5 秒硬性限制**:避免同步 I/O、大量序列化、網路呼叫。必要時分批存檔、優先存核心狀態。

四、最佳實踐總結表

不同場景最佳實踐

場景必做事項禁止事項
一般恢復 (掛起→恢復)還原導航堆疊、刷新過期 UI、延遲載入非關鍵資料重新初始化整個應用、清空使用者輸入
終止後恢復從 LocalFolder 完整還原 SessionState、驗證資料完整性假設記憶體狀態仍在、忽略 PreviousExecutionState
長時間未使用 (天/週)提供「重新開始」選項、清理過期快取強制恢復舊會話 (可能資料已失效)
應用崩潰後啟動PreviousExecutionState == NotRunning (視同冷啟動)、上報崩潰日誌嘗試恢復崩潰前狀態 (資料可能損毀)

五、常見陷阱與避坑指南

  1. 忘記 `deferral.Complete()`:非同步存檔未完成即返回 → 系統判定超時 → 強制終止 → 下次啟動狀態遺失。
  2. 在 `Suspending` 做耗時操作**:資料庫 Vacuum、大檔案壓縮、網路同步 → 超時終止。改為背景任務或啟動時處理。
  3. 未釋放獨佔資源**:媒體播放器未 `Pause()`、感測器未 `Stop()`、檔案流未 `Dispose()` → 掛起期間持續佔用資源 → 系統可能直接終止。
  4. `Resuming` 做重度初始化**:記憶體完整,只需刷新 UI。重度初始化屬於 `Terminated` 後 `OnLaunched` 的工作。
  5. 忽略 `PreviousExecutionState`**:`Terminated` 時未還原狀態、`Suspended` 時重複還原 → 體驗斷裂或例外。
  6. UI 狀態未序列化**:ScrollViewer 捲動位置、SplitView 開合狀態、Tab 選中索引、表單輸入文字 → 使用者切回發現「輸入內容消失、頁面跳回頂部」。

六、延伸:Extended Splash Screen (延遲啟動畫面)

冷啟動/終止恢復若需 > 2 秒初始化 (載入大量資料、資料庫遷移、雲端同步),應實作 **Extended Splash Screen**:

  1. `Package.appxmanifest` → `視覺資產` → `啟動畫面` 設定靜態圖片。
  2. `OnLaunched` 中建立 `ExtendedSplashScreen` 頁面 (繼承 `Page`,顯示相同圖片 + ProgressRing)。
  3. 非同步初始化完成後 `rootFrame.Navigate` 至真正主頁。

總結

Windows 8 應用生命週期的核心契約:**系統承諾盡力保留進程 (掛起),開發者承諾 5 秒內持久化所有可恢復狀態。** 掌握 `Suspending` (存檔)、`Resuming` (刷新)、`OnLaunched` (冷啟動/終止恢復分流) 三大入口,配合 `SuspensionManager` 標準化序列化流程,即可構建「永不遺失狀態、瞬間響應切換」的專業級應用體驗。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved