通用 Windows 平台 (UWP) 應用程式生命週期
本主題介紹通用 Windows 平台 (UWP) 應用程式從啟動到關閉的生命週期。
一點歷史
在 Windows 8 之前,應用程式有簡單的生命週期。 Win32 和 .NET 應用程式正在執行或未執行。 當使用者將他們最小化,或離開它們時,他們就會繼續執行。 這很好,直到便攜式裝置和電源管理變得越來越重要。
Windows 8 引進了具有 UWP 應用程式的新應用程式模型。 概括而言,已新增暫停狀態。 UWP 應用程式會在使用者最小化或切換至另一個應用程式之後不久暫停。 這表示應用程式線程會停止,而且應用程式會留在記憶體中,除非作業系統需要回收資源。 當使用者切換回應用程式時,它可以快速還原到執行中狀態。
對於需要在背景繼續運行的應用程式,有多種方法,例如背景任務、擴展執行和活動贊助執行 (例如,BackgroundMediaEnabled 功能允許應用程式繼續在背景播放媒體)。 此外,即使您的應用程式暫停或甚至終止,背景傳輸作業仍可繼續。 如需詳細資訊,請參閱如何下載檔案。
根據預設,不在前景的應用程式會暫停。 這會導致目前在前景的應用程式省電和更多資源。
暫停狀態為開發人員增加了新的要求,因為作業系統可能會選擇終止暫停的應用程式以釋放資源。 終止的應用程式仍會出現在任務欄中。 當用戶點擊它時,應用程式必須恢復到終止之前的狀態,因為用戶不會意識到系統關閉了應用程式。 他們會認為,當他們在做其他事情時,它一直在背景等待,並期望它處於與他們離開時相同的狀態。 在本主題中,我們將探討如何完成此作業。
Windows 10 版本 1607 引入了另外兩種應用程式模型狀態:在前台執行和在背景運行。 我們將在後續各節中查看這些其他狀態。
應用程式執行狀態
下圖代表從 Windows 10 版本 1607 開始的可能應用程式模型狀態。 讓我們逐步解說 UWP 應用程式的一般生命週期。
應用程式會在啟動或啟動時,以背景狀態輸入執行。 如果應用程式因前景應用程式啟動而需要移至前景,則應用程式會取得 LeavingBackground 事件。
雖然「已啟動」和「已啟動」可能類似詞彙,但它們指的是作業系統可能啟動應用程式的不同方式。 讓我們先看看啟動應用程式。
應用程式啟動
啟動應用程式時會呼叫 OnLaunched 方法。 它會傳遞 LaunchActivatedEventArgs 參數,其中提供傳遞至應用程式的自變數、啟動應用程式之磚的識別碼,以及應用程式所在的先前狀態。
從 LaunchActivatedEventArgs.PreviousExecutionState 取得您應用程式的先前狀態,這會傳回 ApplicationExecutionState。 其值以及由於該狀態而採取的適當操作如下:
ApplicationExecutionState | 說明 | 要採取的動作 |
---|---|---|
未執行 | 應用程式可能處於此狀態,因為自使用者上次重新啟動或登入後尚未啟動。 如果它正在執行,但然後當機,或因為使用者稍早關閉,它也可以處於這個狀態。 | 初始化應用程式,就像是在目前用戶會話中第一次執行一樣。 |
已暫停 | 使用者已最小化或離開您的應用程式,並在幾秒鐘內未返回。 | 當應用程式暫停時,其狀態會保留在記憶體中。 您只需重新取得應用程式暫停時釋放的任何檔案處理常式或其他資源。 |
已終止 | 應用程式先前已暫停,但在某個時間點關閉,因為系統需要回收記憶體。 | 還原使用者離開應用程式時的狀態。 |
ClosedByUser | 用戶以系統關閉按鈕或 Alt+F4 關閉應用程式。 當使用者關閉應用程式時,會先暫停再終止。 | 由於應用程式基本上已經歷導致終止狀態的相同步驟,因此請以您「終止」狀態的相同方式處理此動作。 |
執行中 | 當用戶嘗試再次啟動應用程式時,應用程式已經開啟。 | 不執行任何動作。 請注意,不會啟動您應用程式的另一個執行個體。 已執行中的執行個體只會啟動。 |
注意
目前使用者工作階段是基於 Windows 登入。 只要目前的使用者未註銷、關機或重新啟動 Windows,目前的用戶會話就會持續存在鎖定畫面驗證、切換使用者等事件。
要注意的一個重要情況是,如果裝置有足夠的資源,作業系統會預先啟動已選擇加入該行為的常用應用程式,以優化回應性。 預先啟動的應用程式會在背景啟動,然後快速暫停,如此一來,當使用者切換到它們時,就可以繼續執行比啟動應用程式更快。
由於預先啟動,應用程式的 OnLaunched() 方法可能由系統起始,而不是由使用者起始。 因為應用程式在背景中預先啟動,您可能需要在 OnLaunched() 中採取不同的動作。 例如,如果您的應用程式在啟動時開始播放音樂,則他們不會知道其來自何處,因為應用程式會在背景中預先啟動。 您的應用程式在背景中預先啟動之後,接著呼叫 Application.Suspending。 然後,當使用者啟動應用程式時,會叫用繼續事件以及 OnLaunched() 方法。 如需如何處理預先啟動案例的其他資訊,請參閱處理應用程式預先啟動。 只有選擇加入的應用程式才會預先啟動。
Windows 會在啟動應用程式時顯示啟動顯示畫面。 若要設定啟動顯示畫面,請參閱新增啟動顯示畫面。
顯示初始畫面時,您的應用程式應註冊事件處理程序並設定初始頁面所需的任何自訂 UI。 查看在應用程式建構函式和 OnLaunched() 中執行的這些工作會在幾秒鐘內完成,或系統可能會認為您的應用程式沒有回應並終止。 如果應用程式需要從網路要求資料,或需要從磁碟擷取大量資料,則應該在啟動外部完成這些活動。 應用程式在等待長時間運行的操作完成時可以使用自己的自訂載入 UI 或擴充功能的啟動畫面。 如需詳細資訊,請參閱顯示啟動顯示畫面以取得更多時間和啟動顯示畫面範例。
應用程式完成啟動之後,它會進入執行中狀態,啟動顯示畫面會消失,並清除所有啟動顯示畫面資源和物件。
應用程式啟動
相較於使用者啟動,系統可以啟動應用程式。 應用程式可能會由合約啟動,例如共享合約。 或者,您可以啟動它來處理自定義 URI 通訊協定,或具有應用程式註冊處理之擴展名的檔案。 如需應用程式啟用方式的清單,請參閱 ActivationKind。
Windows.UI.Xaml.Application 類別會定義您可以覆寫的方法,以處理應用程式可能啟用的各種方式。 OnActivated 可以處理所有可能的啟用類型。 不過,使用特定方法來處理最常見的啟用類型比較常見,並使用 OnActivated 作為較不常見啟用類型的後援方法。 以下是特定啟用的其他方法:
OnCachedFileUpdaterActivated
OnFileActivated
OnFileOpenPickerActivated OnFileSavePickerActivated
OnSearchActivated
OnShareTargetActivated
這些方法的事件資料包含我們上面看到的相同 PreviousExecutionState 屬性,這會告訴您應用程式在啟動之前的狀態。 解譯狀態和您應該執行的動作,方式與應用程式啟動一節中所述的方式相同。
注意如果使用電腦的管理員帳號登錄,則無法啟動 UWP 應用程式。
在背景中執行
從 Windows 10 版本 1607 開始,應用程式可以在與應用程式本身相同的程序中執行背景工作。 使用單一程序模型在背景活動中深入瞭解。 我們不會在本文中進行程序背景處理,但影響應用程式生命週期的方式是,當您的應用程式處於背景時,已新增兩個新的事件。 它們是:EnteredBackground 和 LeavingBackground。
這些事件也會反映使用者是否可以看到應用程式的 UI。
在背景中執行是應用程式啟動、啟動或繼續進入的預設狀態。 在此狀態下,您的應用程式 UI 尚未顯示。
在前景中執行
在前景中執行表示您的應用程式 UI 是可見的。
在顯示應用程式 UI 之前,以及在進入前景狀態執行之前,會引發 LeavingBackground 事件。 當使用者切換回您的應用程式時,也會引發它。
先前,載入 UI 資產的最佳位置是在 Activated 或 Resuming 事件處理程式中。 現在 LeavingBackground 是確認 UI 就緒的最佳位置。
請務必檢查目前是否準備好視覺資產,因為這是使用者看到應用程式之前執行工作的最後機會。 此事件處理程式中的所有UI都應該快速完成,因為它會影響使用者體驗的啟動和繼續時間。 LeavingBackground 是確保 UI 第一個畫面已就緒的時間。 然後,應該以非同步方式處理長時間執行的記憶體或網路呼叫,以便事件處理程式可以傳回。
當使用者離開您的應用程式時,您的應用程式會重新進入以背景狀態執行的 。
重新輸入背景狀態
EnteredBackground 事件表示您的應用程式不再顯示在前景中。 在桌面上,當您的應用程式最小化時,EnteredBackground 會觸發; 在手機上,切換到主螢幕或其他應用程式時。
減少應用程式的記憶體使用量
由於使用者不會再看到您的應用程式,因此是停止 UI 渲染工作和動畫的最佳位置。 您可以使用 LeavingBackground 再次啟動該工作。
如果您要在背景中執行工作,這就是準備它的地方。 最好檢查 MemoryManager.AppMemoryUsageLevel,並視需要減少應用程式在背景執行時所使用的記憶體數量,讓應用程式不會有系統終止資源的風險。
如需詳細資訊,請參閱減少應用程式移至背景狀態時的記憶體使用量。
保存您的狀態
暫停事件處理程式是儲存應用程式狀態的最佳位置。 但是,如果您在背景進行工作 (例如,音訊播放、使用擴充功能執行會話或程序內背景任務),從 EnteredBackground 事件處理程序非同步保存資料也是一個好習慣。 這是因為您的應用程式有可能在背景中處於較低優先順序時終止。 而且因為應用程式在該情況下不會經歷暫停狀態,因此您的資料將會遺失。
在背景活動開始之前,將您的資料儲存在 EnteredBackground 事件處理程式中,可確保使用者在將應用程式帶回前景時,有良好的用戶體驗。 您可以使用應用程式資料 API 來儲存資料和設定。 有關詳細資訊,請參閱儲存和檢索設定和其他應用程式資料。
儲存資料之後,如果您超過記憶體使用量限制,則可以從記憶體釋放資料,因為稍後可以重載資料。 這會釋放背景活動所需資產可以使用的記憶體。
請注意,如果您的應用程式正在進行背景活動,它可以從背景狀態中的執行移至前景狀態中執行,而不需要達到暫停狀態。
注意
當使用者關閉您的應用程式時,可以在 EnteredBackground 事件之前引發 OnSuspending 事件。 在某些情況下,在應用程式終止之前,可能不會引發 EnteredBackground 事件。 請務必將資料儲存在 OnSuspending 事件處理程式中。
非同步工作和延遲
如果您在處理常式內進行非同步呼叫,控制項會立即從該非同步呼叫傳回。 這表示,即使非同步呼叫尚未完成,執行狀態仍可從事件處理常式傳回,而且您的應用程式仍會移至下一個狀態。 使用傳遞給您的事件處理常式的 EnteredBackgroundEventArgs 物件上的 GetDeferral 方法,將暫停延遲到在返回的 Windows.Foundation.Deferral 物件上呼叫 Complete 方法之後。
延遲不會增加在應用程式終止之前執行程式碼的時間量。 它只會延遲終止,直到呼叫該延遲的 Complete 方法,或者截止期限到期 (以先到者為準)。
如果您需要更多時間來保存狀態,請研究在應用程式進入背景狀態之前分階段保存狀態的方法,以便在 OnSuspending 事件處理程序中保存較少的內容。 或者,您可以要求 ExtendedExecutionSession 以取得更多時間。 不過,不保證會授與要求,因此最好找到將儲存狀態所需的時間降至最低的方法。
應用程式暫停
當使用者將應用程式 Windows 最小化時,會等候幾秒鐘,以查看使用者是否會切換回該應用程式。 如果未在此時間範圍內切換回 ,且沒有延長執行、背景工作或活動贊助執行作用中,Windows 會暫停應用程式。 當鎖定畫面出現時,應用程式也會暫停,只要沒有延伸執行會話等,該應用程式就會處於作用中狀態。
當應用程式暫停時,它會叫用 Application.Suspending 事件。 Visual Studio 的 UWP 專案範本會針對 App.xaml.cs 中名為 OnSuspending 的這個事件提供處理程式。 您應該在此放置程式代碼來儲存應用程式狀態。
您應該釋放獨佔資源和檔案控制代碼,讓其他應用程式可以在您的應用程式暫停時存取它們。 獨佔資源的範例包括攝影機、I/O 裝置、外部裝置和網路資源。 明確釋放獨佔資源和檔案控制代碼,有助於確保其他應用程式可在您的應用程式暫停時存取它們。 當應用程式繼續時,它應該重新取得其獨佔資源和檔案控制代碼。
請注意期限
為了確保設備快速回應,在暫停事件處理程序中執行程式碼的時間是有限制的。 每個裝置都不同,而且您可以使用稱為期限的 SuspendingOperation 物件屬性來找出它的內容。
如同 EnteredBackground 事件處理程式,如果您從處理程式進行非同步呼叫,控件會立即從該非同步呼叫傳回。 這意味著執行可以從事件處理程序返回,並且即使非同步呼叫尚未完成,您的應用程式也將進入暫停狀態。 使用 SuspendingOperation 物件上的 GetDeferral 方法 (可透過事件參數取得) 來延遲進入暫停狀態,直到對傳回的 SuspendingDeferral 物件呼叫 Complete 方法之後。
如果您需要更多時間,您可以要求 ExtendedExecutionSession。 不過,不保證會授與要求,因此最好找到將暫停事件處理程式中所需時間量降到最低的方法。
應用程式終止
系統會在應用程式暫停時嘗試將應用程式及其資料保留在記憶體中。 不過,如果系統沒有將應用程式保留在記憶體中的資源,將會終止您的應用程式。 應用程式不會收到即將終止的通知,因此您唯一必須儲存應用程式資料的機會是在 OnSuspending 事件處理程式中。
當您的應用程式判斷它已在終止之後啟動時,它應該載入它所儲存的應用程式資料,讓應用程式處於與終止之前處於相同的狀態。 當使用者切換回已終止的暫停應用程式時,應用程式應該在其 OnLaunched 方法中還原其應用程式資料。 系統不會在應用程式終止時通知應用程序,因此您的應用程式必須在掛起之前保存其應用程式資料並釋放獨佔資源和檔案句柄,並在終止後啟動應用程式時恢復它們。
關於使用 Visual Studio 進行偵錯的注意事項: Visual Studio 會防止 Windows 暫停附加至偵錯工具的應用程式。 這是要讓使用者在執行應用程式時檢視 Visual Studio 偵錯 UI。 當您偵錯應用程式時,可以使用 Visual Studio 將暫停事件傳送給應用程式。 確定畫面顯示 [偵錯位置] 工具列,然後按一下 [暫停] 圖示。
應用程式繼續
當用戶切換到暫停的應用程式或當裝置退出低功耗狀態時它是活動應用程式時,暫停的應用程式將恢復。
當應用程式從暫停狀態恢復時,它會進入背景運行狀態,並且系統會將應用程式恢復到其停止的位置,以便用戶看起來就像它一直在運行一樣。 不會遺失儲存在記憶體中的應用程式資料。 因此,大部分的應用程式在繼續時不需要還原狀態,不過它們應該重新取得在暫停時釋放的任何檔案或裝置句柄,以及還原應用程式暫停時明確釋放的任何狀態。
您的應用程式可能會暫停數小時或數天。 如果您的應用程式的內容或網路連線可能已過時,則應用程式繼續時應該重新整理這些連線。 如果應用程式為 Application.Resuming 事件註冊了事件處理程序,則當應用程式從暫停狀態復原時會呼叫該事件處理程序。 您可以在此事件處理程式中重新整理應用程式內容和資料。
如果已掛起的應用程式啟動以參與應用程式合約或擴展,則它會先收到 Resuming 事件,然後收到 Activated 事件。
如果暫停掛起的應用程式被終止,則不會有 Resuming 事件,而是會呼叫 OnLaunched(),並使用 Termminate 的 ApplicationExecutionState。 由於您在應用程式暫停時保存了狀態,因此您可以在 OnLaunched() 期間恢復該狀態,以便用戶看到您的應用程式就像他們離開應用程式一樣。
當應用程式暫停時,它不會收到任何已註冊要接收的網路事件。 這些網路事件不會排入佇列,它們只會遺漏。 因此,您的應用程式應該在繼續時測試網路狀態。
注意由於 Resuming 事件不是從 UI 執行緒引發的,因此如果復原處理程序中的程式碼與 UI 進行通信,則必須使用排程器。 有關如何執行此操作的程式碼範例,請參閱從背景執行緒更新 UI 執行緒。
如需一般指導方針,請參閱應用程式暫停和繼續的指南。
應用程式關閉
一般而言,使用者不需要關閉應用程式,他們可以讓 Windows 管理它們。 不過,使用者可以選擇使用關閉手勢或按 Alt+F4 或使用 Windows 電話 上的工作切換器來關閉應用程式。
沒有事件指示使用者關閉了應用程式。 當使用者關閉應用程式時,會先暫停它,讓您有機會儲存其狀態。 在 Windows 8.1 和更新版本中,在使用者關閉應用程式之後,應用程式會從畫面移除並切換清單,但未明確終止。
關閉的使用者行為: 如果您的應用程式在使用者關閉時需要執行與 Windows 關閉時不同的動作,您可以使用啟用事件處理程式來判斷應用程式是由使用者或 Windows 終止。 請參閱 ApplicationExecutionState 枚舉參考中對 ClosedByUser 和 Termerated 狀態的描述。
除非絕對必要,否則建議應用程式不要以程序設計方式關閉自己。 例如,如果應用程式偵測到記憶體流失,它可以自行關閉以確保使用者個人資料的安全性。
應用程式損毀
系統當機體驗的設計目的是讓用戶儘快回到他們所做的工作。 您不應該提供警告對話方塊或其他通知,因為這會延遲使用者。
如果您的應用程式當機、停止回應或產生例外狀況,則會根據使用者的意見反應和診斷設定,將問題報告傳送給 Microsoft。 如需詳細資訊,請參閱 Windows 中的診斷、意見反應和隱私權。 Microsoft 會提供問題報告中錯誤資料的子集給您,讓您能夠使用它來改善您的應用程式。 您將能夠在儀表板的應用程式品質頁面中看到此資料。
當使用者在崩潰後啟動應用程式時,其啟動事件處理程序會收到 NotRunning 的 ApplicationExecutionState 值,並且應顯示其初始 UI 和資料。 崩潰後,不要經常使用原本用於暫停恢復的應用程式資料,因為該資料可能會損壞;請參閱應用程式暫停和恢復指南。
應用程式移除
當使用者刪除您的應用程式時,會移除應用程式及其所有本機資料。 拿掉應用程式不會影響儲存在檔或圖片庫等常見位置的用戶資料。
應用程式生命週期和 Visual Studio 專案範本
Visual Studio 專案範本中會提供與應用程式生命週期相關的基本程序代碼。 基本應用程式處理啟動,為您提供恢復應用程式資料的位置,並在您添加任何自己的程式碼之前顯示主 UI。 有關詳細資訊,請參閱應用程式的 C#、VB 和 C++ 專案範本。
主要應用程式生命週期 API
- Windows.ApplicationModel 命名空間
- Windows.ApplicationModel.Activation 命名空間
- Windows.ApplicationModel.Core 命名空間
- Windows.UI.Xaml.Application 類別 (XAML)
- Windows.UI.Xaml.Window 類別 (XAML)