在手機上,使用後臺,不像電腦上那麼隨意,準確地講嘛,在移動平臺上,後臺任務都有嚴格的限制。至於說爲何會有這麼多限制,我估計初衷很明顯——保證系統的性能不受某個或某幾個應用的負面影響;另外就是出於安全性考慮。安全
畢竟手機設備不一樣於電腦,一旦後臺程序氾濫成災,是很難進行管理的,要防止這些不可預知的事件,只能從源頭上杜絕。所以,當初在RT應用上就是:容許後臺任務,但你得按規矩作人。網絡
無規矩不成方圓,沒有限制就會亂象橫生,沒法控制,如今某手機系統就深陷這一問題沒法自撥,WP沒有必要重蹈這一覆轍。app
好,前面廢話了那麼多,就是要告訴你們,在開發的時候必定要想清楚,到底該不應使用後臺任務,使用後臺任務的話,必定要本身親測一下,是否會明顯消耗電量,是否會產生龐大的網絡流量。你們必定要養成一個好習慣——以作流氓程序爲恥。說到這裏,不得不鄙視一下國內的某些公司。async
既而後臺任務是有限制的,那麼,官方是經過什麼方式來限制的呢?函數
觸發器:後臺任務必須經過觸發器來執行。這個觸發器,能夠理解爲相似生物的條件反射。清單文件給出的觸發類型有:後臺音頻、計時器、系統維護等。記得前面我寫過博客,弄了一個在點亮屏幕時播放音樂,雖然這種作法不盡合理,但也做爲一種參考吧。那個示例就是經過系統觸發器中的UserPresent類型觸發的,就是當用戶把手機屏幕點亮這一行爲發生後就會執行後臺任務。工具
好比,比較經常使用的還有計時器,這個應該會用得較多,好比每隔一段時間提取一批新聞列表等,如每30分鐘就執行一次。固然這計時器是有限制的,常規要求是至少15分鐘。否則的話,一些人品不端正的開發者弄個每分鐘觸發一次,那還得了,若是它是提取廣告的話,那不斷地彈廣告就會把用戶彈傻了。你們千萬別幹這種事,你要幹這種事,我只能說你太沒出息。性能
凡是實現了IBackgroundTrigger接口的都是觸發器,常以「Trigger」結尾,並非全部觸發器都能用,有些是須要申請的,好比ChatMessageNotificationTrigger,這也是防止惡意程序的作法。ui
執行條件:這個主要由SystemCondition類表示。執行條件與觸發器不一樣,觸發器是代表在什麼事實發生後執行後臺任務,而執行條件是在什麼狀況下才能執行後臺任務。你聽起來好像意思接近,其實是不一樣的。好比,若是你的後臺任務須要從網絡上獲取數據,並且觸發器爲每25分鐘一次的計時器,因而在註冊後臺任務時,你能夠考慮增長一個執行條件:在有網絡鏈接的前提下執行。雖然計時器的時間到了,但正好這個時候,因爲用戶的手機卡欠下4G流量費8622000元,被停機了,無法上網,那麼系統檢測到不存在有效的網絡鏈接,就不執行後臺任務了(能夠考慮用WiFi)。spa
前面扯了一堆臊話,主要是讓朋友們對後臺任務有個大體的瞭解,如今向你們介紹如何用後臺。.net
表明後臺任務的代碼一般應該寫在一個獨立的組件中,這樣作也比較科學的,有些朋友在開發程序時,喜歡把全部功能都塞到一個主程序裏,許多人在開發桌面程序時就喜歡這樣,把全部功能都塞進一個exe中,連.dll都不捨得多用一個,我不喜歡這樣作的,通常我是一個功能模板用一個獨立的.dll,至於.exe用來放UI或者一些核心處理。
所以,第一步是向解決方案中添加一個Windows運行時組件,看清楚,是運行時組件,最後會生成.wimd文件,若是是類庫就會生成.dll文件。後臺任務都應寫在Windows運行時組件中。這個應該會了吧,就是在「解決方案資源管理器」中新建項目,而後選Windows運行時組件,輸入項目名字就能夠了,若是你不會這個,我只能告訴你:基礎不紮實,舉步艱難。
而後在新建的運行時組件中定義一個類,必定要是public的,不要問我爲何(請複習程序集的可訪問性),這個類要實現IBackgroundTask接口,表示它用於執行後臺任務。
public sealed class DemoTask : IBackgroundTask { public void Run ( IBackgroundTaskInstance taskInstance ) { } }
重點是實現Run方法,當後臺任務執行時,就是調用這個方法的,你的後臺任務要作什麼就寫在Run裏面。
注意到有個IBackgroundTaskInstance類型的參數,是個接口,咱們不用管它哪一個類實現,這個在系統調用時會自動賦值,只關心它有哪些成員便可。
必定要明白GetDeferral方法的做用,它能夠返回一個BackgroundTaskDeferral對象,這個對象的做用,說簡單一點就是用來拖延時間的,就是拖延後臺任務的時間,當你以爲後臺任務已經完成了,就調用用BackgroundTaskDeferral的Complete方法,告訴系統:任務作完了,系統收到報告後,就能夠清理該任務了。
如今咱們來實現一下這個任務。
public void Run ( IBackgroundTaskInstance taskInstance ) { var def = taskInstance.GetDeferral(); // 獲取XML模板 XmlDocument docx = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); // 修改XML var eles = docx.GetElementsByTagName("text"); if (eles.Count < 2) { def.Complete(); return; } XmlElement text01 = (XmlElement)eles[0]; text01.AppendChild(docx.CreateTextNode("示例")); XmlElement text02 = (XmlElement)eles[1]; text02.AppendChild(docx.CreateTextNode("後臺任務執行了。")); // 產生Toast通知 ToastNotification notification = new ToastNotification(docx); // 顯示通知 ToastNotificationManager.CreateToastNotifier().Show(notification); // 報告任務完成 def.Complete(); }
這個任務,不復雜,就是向用戶發一條Toast通知。
好,後臺任務已經寫好了,如今要在主項目中對它進行引用,必定不要忘了,只有引用了上面寫的Windows運行時組件才能訪問它,這和之前.net項目同樣。
這個後臺任務,我打算讓它每40分鐘執行一次,因此觸發器應選用TimeTrigger。下面先簡單設計一下UI。
<StackPanel> <Button Content="註冊後臺任務" Click="開始註冊"/> <Button Content="取消後臺任務" Click="取消註冊"/> <TextBlock x:Name="tb" FontSize="20" TextWrapping="Wrap"/> </StackPanel>
界面簡單,你看得懂的,其實事件處理的方法名是能夠用中文的,在VS裏面,類型名、命名空間名、成員名、參數名均可以用中文的,若是你不喜歡英文名字,能夠用中文。
一般,註冊後臺任務須要準備如下證件:
一、我的身份證,即後臺任務的名字,這個名字必須惟一,不能與現有的任務重複。
二、戶口本。即入口點,指的是咱們前面在Windows運行時組件中定義的那個類的類名,就是那個實現IBackgroundTask接口以及Run方法的類。
爲了在輸入代碼時不容易輸入,最好先將這些內容聲明爲常量。
/// <summary> /// 任務的惟一名稱 /// </summary> const string TASK_NAME = "haha_task"; /// <summary> /// 入口點 /// </summary> const string ENTRY_POINT = "BackTest.DemoTask";
注意,入口點的名字是要包含命名空間名字的。
好,前期手續基本辦完,如今能夠正式註冊了。下面代碼分別用於註冊和取消註冊後臺任務。
private async void 開始註冊 ( object sender, RoutedEventArgs e ) { var res = await BackgroundExecutionManager.RequestAccessAsync(); if (res != BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity) return; // 註冊 BackgroundTaskBuilder bd = new BackgroundTaskBuilder(); bd.Name = TASK_NAME; //任務名 bd.TaskEntryPoint = ENTRY_POINT; //入口點 // 設置觸發器爲計時器 bd.SetTrigger(new TimeTrigger(40, false)); try { BackgroundTaskRegistration reg = bd.Register(); // 註冊成功,顯示結果 tb.Text = string.Format("任務名:{0}\n任務ID:{1}", reg.Name, reg.TaskId); } catch (Exception ex) { tb.Text = ex.Message; } } private void 取消註冊 ( object sender, RoutedEventArgs e ) { // 先查找一下是否已經註冊了任務 var task = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault(t => t.Name == TASK_NAME); if (task != null) { // 取消 task.Unregister(true); } }
一、在註冊以前必定要調用BackgroundExecutionManager.RequestAccessAsync方法,是然不會彈出任何提示,但不要忘了,不調用是不能註冊的。
二、BackgroundTaskBuilder類,顧名思義,就是用來註冊後臺任務的。
三、TimeTrigger觸發器的構造函數的第二個參數若是爲true,那後臺任務只運行一次,這裏我但願它每40分鐘運行一次,因此爲false。
如今,離成果不遠了,可是還有一步很關鍵,那就是配置清單文件。
打開Package.appxmanifest文件,切換到「聲明」選項頁,在可用的聲明列表中選「後臺任務」,而後點擊添加按鈕。
在右邊的頁面中,按實際狀況勾選,我這個例子是計時的,因此選計時器,而後在下面再填寫一下入口點,這個入口點和註冊後臺任務時用的入口點是同樣的,能夠直接從剛纔的代碼中複製過來。
由於本例要用到Toast通知,因此要讓應用支持Toast。切換到「應用程序」選項卡,在下面有關通知設置的地方,將支持Toast通知設置爲「是」。
最後,保存並關閉清單文件。
像我這個例子,要等40分鐘才執行的,難道我在乾等不成? 非也,咱們不用在那裏苦等40分鐘,VS會幫助咱們進行調試的。
首先,運行應用程序,而後點頁面上的註冊按鈕,確保後臺任務已經成功註冊。
而後回到VS,在「調試位置」工具上,點擊「生命週期事件」按鈕右邊的下拉箭頭,從下拉菜單中你會看到有後臺任務的名字。以下圖。
若是看不到,你能夠稍等一下,若是一直不出現,你能夠重複上面的步驟。只要後臺任務註冊成功的,確定會顯示的(後臺音頻和推送通知除外)。
因此,如今你調試後臺任務就很方便,直從「調試位置」工具欄的下拉菜單中選中後臺任務,後臺任務就會執行了。
OK,相信經過這篇破文,初學者可以初步認識後臺任務。