【WP8.1開發】認識後臺任務

在手機上,使用後臺,不像電腦上那麼隨意,準確地講嘛,在移動平臺上,後臺任務都有嚴格的限制。至於說爲何會有這麼多限制,我估計初衷很明顯——保證系統的性能不受某個或某幾個應用的負面影響;另外就是出於安全性考慮。安全

畢竟手機設備不一樣於電腦,一旦後臺程序氾濫成災,是很難進行管理的,要防止這些不可預知的事件,只能從源頭上杜絕。所以,當初在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,相信經過這篇破文,初學者可以初步認識後臺任務。

示例源碼:http://files.cnblogs.com/tcjiaan/SampleAppBackTask.zip

相關文章
相關標籤/搜索