Windows 10 UWP 5 of N : Application Life Management
不論甚麼平台應用程式都會有生命週期,那..生命週期之所以重要就是要妥善的利用系統資源如:CPU、RAM、Network、Battery Power...等。
那麼在Windows 10 UWP應用程式的生命週期又有怎樣的變化呢?
一樣的是總有三種狀態:
- Running
- Suspended
- Not Running
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.Resuming += OnResuming;
}
一開始APP都會是在Not Running的狀態! 接著App會先進行InitializeComponent初始化整體App的核心元件,然後會進入到OnLaunched的事件然後才會由Not Running的狀態轉換到 Running的狀態!
接者當User切換到別的APP的時候將會觸發 Suspending的事件然後在Suspending的事件中可以使用如下Code達到儲存資料的功能
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
呼叫GetDeferral來給予多餘時間進行儲存的機制但Deferral只給予大約5秒鐘的時間進行資料儲存!
在Windows 10 UWP上在Foreground execution可以呼叫Extended Execution來稍微延長儲存的時間!
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
using (var session = new ExtendedExecutionSession())
{
session.Reason = ExtendedExecutionReason.SavingData;
session.Description = "Save data to cloud!";
session.Revoked += Session_Revoked;
var result = await session.RequestExtensionAsync();
if (result == ExtendedExecutionResult.Allowed)
{
await SaveDataCloudAsync();
}
}
deferral.Complete();
}
以下是幾點關於ExtendedExecutionSession的重點
屬性 | 型別 | 說明 |
Reason | Enum |
Unspecified LocationTracking (必填屬性,目前只有三種) |
Description | String | 說明字串 |
PercentProgress | uInt32 | 百分比進度 |
方法 | 說明 |
RequestExetensionAsync | 向系統要求更多時間(約3秒延遲被Suspended) |
Dispose | 釋放掉Session,建議使用Using包起來就好。 |
事件 | 說明 |
Revoked | 給予小於1秒的時間清除session或其他資源釋放。 |
呼叫完成RequestExetensionAsync會給予Allow或著Denied!基本上一律會給予Allow的。
如果要測試Application life cycle在Visual Studio的Toolbar上開啟Debug location就可以找到
然後再執行APP的Debug的時候就可以展開Lifecycle的選項。
進去Suspend的時候就可以額外要求多餘的等待時間!
當然一樣的是如果超過約3秒的時間將會一樣被系統強制關閉!這個機制依然會參考系統的忙碌狀況,在不同硬體裝置上會有所差異。
APP如果被Suspended之後可以依然執行的唯一方法就是Background Execution
像是Trigger base Background Tasks就是APP註冊這些Trigger就可以被觸發當Trigger被啟動的時候。
例如:
- Push notification
- Geofencing
- BLE device
- Timer
- App Services
基本上與之前Universal App 8.1 時期差不多!多了不少的Trigger並將Phone以及Store的Trigger做整合。
原先Windows Store 8.1有以下的Triggers
- SystemTrigger
- TimeTrigger
- MaintenanceTrigger
- DeviceUseTrigger
- DeviceServicingTrigger
- PushNotificationTrigger
在Windows Phone 8.1有以下的Triggers
- CachedFileUpdaterTrigger
- DeviceConnectionChangeTrigger
- GattCharacteristicNotificationTrigger
- RfcommConnectionTrigger
- LocationTrigger
然後以下是Windows 10新增的Trigger
- AppointmentStoreNotificationTrigger
- ContactStoreNotificationTrigger
- BluetoothLEAdvertisementWarcherTrigger
- BluetoothLEAdvertisementPublisherTrigger
- DeviceWatcherTrigger
- ActivitySensorTrigger
- SensorDataThresholdTrigger
- ToastNotificationHistoryChangedTrigger
- ToastNotificationActionTrigger
- ApplicationTrigger
- SocketActivityTrigger
接者複習一下Trigger八~
假設需要一個TimerTrigger回報背景下載進度可以用以下方式來測試。
先是開啟一專案,在UWP的專案類型只有
- Blank
- Class Library
- Windows Runtime Component
- Unit Test App
- Download Windows Universal Tools
選擇Runtime專案類型並在Reference加入該Project
將Component專案加入APP專案後打開Manifest檔案,建議使用XML的編輯器開啟並加如以下Code
<Extensions> <Extension Category="windows.backgroundTasks" EntryPoint="SampleComponet.BackgroundTask.TimerTask"> <BackgroundTasks> <Task Type="timer"/> </BackgroundTasks> </Extension> </Extensions>
在Application的程式碼區段!EntryPoint就是該Component的NameSpace以及使用的TriggerTask的名稱所組合的路徑。
接著在Application中註冊BackgroundTrigger
private async void RegisterBackgroundTasks(String taskName, Type taskType, IBackgroundTrigger triggerInstance, IBackgroundCondition triggerCondiction = null)
{
if (BackgroundExecutionManager.GetAccessStatus() != BackgroundAccessStatus.Denied)
{
var backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();
foreach (var task in BackgroundTaskRegistration.AllTasks)
{
if (task.Value.Name == taskName)
{
task.Value.Unregister(true);
}
}
}
var backgroundTaskBuilder = new BackgroundTaskBuilder();
backgroundTaskBuilder.Name = taskName;
backgroundTaskBuilder.TaskEntryPoint = taskType.FullName;
backgroundTaskBuilder.SetTrigger(triggerInstance);
if (triggerCondiction != null)
backgroundTaskBuilder.AddCondition(triggerCondiction);
var taskRegistration = backgroundTaskBuilder.Register();
System.Diagnostics.Debug.WriteLine(string.Format("{0} is registed!", taskRegistration.Name));
}
一開始先必須將之前的BackgroundTask解除註冊在進行新的Trigger的註冊!
接者在去Component的Trigger實作IBackgroundTask
public sealed class TimerTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.Canceled += TaskInstance_Canceled;
#if DEBUG
ShowToast("WTF");
#endif
}
private void TaskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
}
private void ShowToast(String toastMessage)
{
var toastTemplate = ToastTemplateType.ToastText01;
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);
var toastTextElements = toastXml.GetElementsByTagName("text");
toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastMessage));
var toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
}
BackgroundTaskInstance就是觸發的Task而且支援Deferral的機制處裡一些非同步的方法!
簡單測試BackgroundTask的方式就是一樣在Debug location的Tool中找到ALM的選單,然後切換到BackgroundTask的Class檔就會出現該trigger的選項出現
這樣就可以測試BackgroundTask的功能了!
Universal Windows App上的Background Task以資源管理分成以下兩類
類型 | 記憶體使用(MB) | 執行時間 | CPU | 使否會售電池管理影響 |
Default | 16 | 30 secs | 10% | 是 |
Long-Running ( Opportunistic ) | 16 | 無限 | 10% | 是 |
預設的Background Task都擁有25秒的執行時間和5秒的取消時間!當然這些執行的時間會受系統資源多寡影響。
ApplicationTrigger, MaintenanceTrigger, DeviceUseTrigger 都是Opportunistic的BackgroundTask.
然後介紹一下In-Process的Background Task。
預設的BackgroundTask的實際執行exe和Background Task的exe使兩個不同的exe檔案所以是不同的Process而記憶體的使用也是分開的!而在UWP有InProc的Background Task就是將App的exe和BackgroundTask的exe綁在同一個process下並且共享記憶體區塊!
使用InProc的BackgroundTask只需要在Manifest檔案的 Extension做以下變更。
<Extension Category="windows.backgroundTasks" EntryPoint="SampleComponet.BackgroundTask.TimerTask" Executable="App1.exe">
<BackgroundTasks>
<Task Type="timer"/>
</BackgroundTasks>
</Extension>
加上Executable並給上執行的App的exe名稱就可以和Foreground Application在同一Process下執行。
***以上Code以及說明都有可能隨著Windows 10 的版本以及Visual Studio 2015版本有所調整!***
參考資料 Build 3-626 Windows App Lifecycle ( From Activation & Suspension to Background Execution and Multitasking )
下次再分享Windows 10 的新技術拉~