修鍊九陰真經Windows Phone開發 (12):計劃任務Background Schedule Tasks總結及樣本

來源:互聯網
上載者:User

在WP7.1中針對Background Agent的新API增加了蠻多非常強大的部分,以下將介紹Scheduled Multi Tasking的部分。

  Scheduled Multi Tasking主要是讓Application支援多工模式來執行任務,讓Application不在前景模式下也可以繼續在背景執行某些特定的任務,例如:背景下載、背景更新資料、背景呼叫服務…等。

  然而,WP7.1提供Agent的模式,讓開發Application時將要背景執行的邏輯,獨立放置於Agent之中透過排程來完成任務。

  但要注意的是,Agent與Application必竟還是屬於不同的專案,因為IsolatedStorage中的IsolatedStorageSettings無法共用,要交換資料需透過IsolatedStorage檔案或其他方式來交換。

  因此,在設計一個支援Background Agent(ScheduledTaskAgent)的Application時,我個人會有幾個考量:

  1. 將背景執行的邏輯獨立成一個類別或模組,由該模組完成所有背景的任務;

  2. 使用設定檔(config)的方式,將參數或執行結果獨立於檔案,提供Application與Agent均可以取得;

  3. Agent是背景的任務,在背景發生Exception的容錯機制需要特別設計,盡量透過通知告知使用者;

  接下來,將細部去討論Scueduled Tasking由那些重要的元素組成:

  〉Microsoft.Phone.Scheduler - Scheduled Multi Tasking:

  WP7.1允許Schedule Task與Background Agent在背景執行它們的任務,然而Schedule Task與Background Agent使用上卻有所不同:

  ‧Schedule Task:重點在於指定「期性/延遲性」執行任務,透過設定Schedule的時間頻率重覆地去執行任務;

  ‧Background Agent:根據不同的Agent可在細分使用重點,但較屬性一次性任務或接收外來事件所觸發的任務;

  在Microsoft.Phone.Scheculer針對Scheulde提供了Task與Notification的使用,其用法上Schedule Task又是另一種用途,針對Schedule Notification會在另一篇<>進行說明。

  然而,在Scheulde Task的使用上有幾個重要元系一定要去瞭解的,以下將詳細說明:

  A. ScheduledActionService:

  專用於管理該裝置所有的Scheduled Actions。Scheduled Actions包括了可用於通知的Alarm、Reminder,更包括下方介紹的二個運行於Background Agent的Periodic Task與Resource-Intensive Task。其重要的方法如下:

名稱 說明
Add 向作業系統冊一個Scheduled Action。主要透過Scheduled Action的Name做為識別值。
Find 透過特定的Name找出Scheduled Action。
GetActions(Of T) 回傳系統中所有特定類型的Scheduled Actions。
LaunchForTest 指定特定的延遲時間與ScheduledTask後,要求Background Agent執行該ScheduledTask。
Remove 從Scheduled Action Service將指定的名稱的Scheduled Action移除。
Replace 通常會配合Find找出指定Name的Scheduled Action,並加以取代它。

 

  B. PeriodicTask:

  Periodic(定期) Task是一種定期代理運作的觀念,專門針對運作背景任務所需時間較少,而且是執行隔間具有規律期性的情境。

  常見的使用情境,例如:定期上傳手機的Location資訊、完成少量資料的同步、更新Tile狀態…等。

  B-1. 使用Periodic Task的約束與時間期建議

約束/建議 說明
排程時間間隔:30分 通常每30分執行一次,在電力狀況不錯的情形下可以配合其他background process使用時,也可以設定接近上下差距10秒的使用。
排程期間 通常支援持續執行25秒,但也可能因為其他原因造成該agent被提早結束。
電池為節約模式時,能防止Exception 由於電池是否要使用節約模式是由使用者自行選擇。如果該模式被選擇時,當電池進入節約模式時,periodic task將有可能無法使用。
每一個裝置在Periodic Task的限制 為了讓電池最大化使用,不同的裝置對電池的使用有一定的控制圍,因此,可能限制一個裝置最多有幾個Agent可以被執行,如果超過,它會自動被turn off。

 

  C. ResourceIntensiveTask:

  Resource-Intensive(資源密集) Task是針對需要相對較長的處理時間,或是遇到需使用大量手機電源、網路等資源時較為適用的類型。

  常見的使用情境,例如:同步大量的資料(如App需要下載大量的資料至手機端才能讓App運行)…等。

  C-1. 使用ResourceIntensiveTask的約束與時間期建議

約束/建議 說明
期間:10分 通常resource-intensive agent一般執行持續約10分,如果有其他如下方的限制,將會提早停止agent的執行。
外部電力需求 除非裝置已串連外部的電力來源,否則無法執行。
無行動網路能線能力 除非裝置已通過Wi-Fi、行動網路或串連到PC,否則無法執行。
最小電力需求 除非電力超過90%的情形,否則無法執行resource-intensive agent
裝置螢幕被鎖定狀態 除非電話處於鎖定的狀態,否則無法執行resource-intensive agent
通話中無法使用 當手機處於通中狀態時,resource-intensive agent無法使用。
不能改變網路狀態為行動網路 如果resource-intensive agent企圖去呼叫AssociateToNetworkInterface(Socket, NetworkInterfaceInfo)來指定任何一種行動網路(GSM或CDMA),則會失敗。

 

  這二個元素其實都是由ScheduleAction與ScheduledTask抽象類別實作出來的,它們分別有自身使用的情境與適用性,

  二者最大的差別即在於使用情境與需要耗用手機資源的多少,以及resource-intensive task要在螢幕鎖定與電力90%以上才能執行。

  由於使用resource-intensive task要求的限制實在很多,因此,在設計Scheduled Task時需要特別考慮這個部分,至於其他相關的

  屬性就大同小異了,以下簡介其較長使用到的屬性:

名稱 說明
Description 設定/取得有關該Scheduled Task的描述。該描述的內容將會出現於手機「Settings/Applications/Background Tasks Settings」的畫面中。
如:以Background Scheulde為程式名稱:
ExpirationTime 設定/取得Scheduled Task到期的時間。
IsScheduled 取得Scheduled Task狀態是否為啟動。
LastExitReason 取得Agent執行最近一次Task被結束的理由。
LastScheduledTime 取得Agent執行最近一次Task的時間,以手機時間為主。
Name 取得Scheduled Action的名稱。

 

  瞭解了二個元素的基本屬性與使用情境後,有幾個使用Background Agent要特別注意的:

  1. 一個Application只能有一個Background agent(ScheduledTaskAgent),但Agent可以單獨使用PeriodicTask、ResourceIntensiveTask

  或者二個同時使用。要注意的是一個Agent只能有一個PeriodicTask與一個ResourceIntensiveTask。

  2. Background Agent(ScheduledTaskAgent):

  2-1. 透過OnInvoke(ScheduleTask)觸發Agent邏輯的部分;

  2-2. 已成功執行完所有任務時,記得呼叫NotifyComplete()告知Agent已完成任務;

  2-3. 如果在執行過程發生錯誤或是無法執行Task時,要記得呼叫Abort()告知Agent接下來取消運作,然而即可以在Application端取得

  ScheduledTask中的IsScheduled屬性為false。但要注意的是如何Abort()之後,要記得使用ShellToast告知使用者,以免使用者不知道。

  3. Background Agent在記憶體使用量的控制:

  3-1. Periodic agents與resource-intensive agents允許在每次執行Task時,不超過6MB記憶體用量。

  3-2. Audio agents則限制不能超過15MB記憶體用量。

  3-3. 在Debug模式下則不限制,但可以透過API去查詢在每一個部分使用記體憶的狀況。

  4. 預設Agent為二個星期後需要重新安排Scheduled:

  雖然可以透過ScheduledTask中的LastScheduledTime去確認究竟最近一次執行的Datetime為何,並且使用ExpirationTime去指定Task

  可啟動並執行時間長度。但是使用ScheduledTask可能因為條件限制(例如遇到執行Task時沒網路能力,自動要求Agent延後執行),造成Task

  長時間沒有被執行,為了確保Task不會一直佔住不使用,透過設定2個星期可存活時間,可以自動解決這個問題。設定ExpirationTime可

  在每一次執行Application於前景狀況時,進行判斷與設定。

  5. Scheduled Agent在連續二個Crash後自動取消:

  由於使用Periodic agents與resource-intensive agetns是交由Agent去控制,因此,當Agent連續出現二次以上的Crash或無法預期的錯誤,

  該Agent將會被停止,需透過Application回到前景模式再重新啟動它。

〉例說明:

  由於Resource-Intensive Task比較不易呈現,因此,例將使用Periodic Task當作主要實作在Background Agent中呼叫Web Service程式,

 

  並且更新Secondary Tile的Background Title與Background Content。

 

  a. 建立一個Web Service,用於ScheduledTaskAgent呼叫時,可以用於更新Tile的內容,撰寫完記得發至iis;

 

   1: [WebMethod]
   2: public string GetSystemDatetime()
   3: {
   4:     //回系,示於Tile的Background Content/Title
   5:     return string.Format("system: {0}", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
   6: }

 

  b. 建立scheduled task agent,並加入Web service參考,設定非同步更新任務;

 

  b-1. 當onInvoke發生時,先宣告Web Service物件並且冊Completed事件,最後呼叫Web Service。但要記得先不要加上NotifyComplete(),

 

  因為Agent要執行的任務尚未結束。

 

   1: protected override void OnInvoke(ScheduledTask task)
   2: {
   3:     //TODO: Add code to perform your task in background
   4:     if (task.Name == PTASKNAME)
   5:     {
   6:         //始初化Web Service的Soap Client元素
   7:         BgService.Service1SoapClient tSoapClient = new BgService.Service1SoapClient();
   8:         //Completed要理的任
   9:         tSoapClient.GetSystemDatetimeCompleted += new System.EventHandler<BgService.GetSystemDatetimeCompletedEventArgs>
(tSoapClient_GetSystemDatetimeCompleted);
  10:         tSoapClient.GetSystemDatetimeAsync();
  11:         //此不加上NotifyComplete(),因需要等到Web Service的回值回才算束。
  12:     }
  13:     else
  14:     {
  15:         //如果不是指定的task, 代表不需要行
  16:         NotifyComplete();
  17:     }
  18: }

  b-2. 撰寫當Web Service處理完成後,將要更新Secondary Tile的內容;

 

  要注意如果執行完成後,需要在期性執行該任務,記得在加上ScheduledActionService.LaunchForTest的指令;

 

   1: void tSoapClient_GetSystemDatetimeCompleted(object sender, BgService.GetSystemDatetimeCompletedEventArgs e)
   2: {
   3:     if (e.Error == null)
   4:     {
   5:         //找出要更新的Tile且整式
   6:         StandardTileData tTileData = new StandardTileData
   7:         {
   8:             BackgroundImage = new Uri(string.Format("/Images/{0}.png", "taipei"), UriKind.Relative),
   9:             Title = "Bg Sample",
  10:             Count = 0,
  11:             BackTitle = "取得service",
  12:             BackContent = e.Result,
  13:             BackBackgroundImage = new Uri("/Images/red.png", UriKind.Relative)
  14:         };
  15:         ShellTile tUsedTile = ShellTile.ActiveTiles.FirstOrDefault(
  16:                           tX => tX.NavigationUri.ToString().Contains(string.Format("Key={0}", PTASKNAME)));
  17:         if (tUsedTile != null)
  18:         {
  19:             tUsedTile.Update(tTileData);
  20:         }
  21:         //如果需要期性行,需要加上下方程式段
  22:         //ScheduledActionService.LaunchForTest(PTASKNAME, TimeSpan.FromSeconds(10));
  23:     }
  24:     else
  25:     {
  26:         //生也要送出Toast告用
  27:         ShellToast toast = new ShellToast();
  28:         toast.Title = "Error";
  29:         toast.Content = e.Error.Message;
  30:         toast.Show();
  31:     }
  32:     NotifyComplete();
  33: }

  c. 建立Application,加上建立tile與啟動periodic task的功能,並且將scheduled task agent與Web Service加入專案參考;

 

  c-1. 撰寫按鈕事件,在確認Tile中沒有指定的Key時才可以建立ScheduledTask與Tile;

 

   1: private void Button_Click(object sender, RoutedEventArgs e)
   2: {
   3:  
   4:     ShellTile tUsedTile = ShellTile.ActiveTiles.FirstOrDefault(
   5:                           tX => tX.NavigationUri.ToString().Contains(string.Format("Key={0}", PTASKNAME)));
   6:     if (tUsedTile == null)
   7:     {
   8:         //Scheduled Task Agent
   9:         gPeriodicTask = new PeriodicTask(PTASKNAME);
  10:         gPeriodicTask.Description = "BgScheduledAction Sample, update tile by webserivce";
  11:         ScheduledActionService.Add(gPeriodicTask);
  12:         PeriodicStackPanel.DataContext = gPeriodicTask;
  13:         ScheduledActionService.LaunchForTest(PTASKNAME, TimeSpan.FromSeconds(10));
  14:  
  15:         //加入tile
  16:         StandardTileData tTileData = new StandardTileData
  17:         {
  18:             BackgroundImage = new Uri(string.Format("/Images/{0}.png", "taipei"), UriKind.Relative),
  19:             Title = "Bg Sample",
  20:             Count = 0,
  21:             BackTitle = "null",
  22:             BackContent = "null",
  23:             BackBackgroundImage = new Uri("/Images/red.png", UriKind.Relative)
  24:         };
  25:         //建立Secondary Tile,且指定Tile後要的Page
  26:         Uri tUrl = new Uri(string.Format("/MainPage.xaml?Key={0}", PTASKNAME), UriKind.Relative);
  27:         ShellTile.Create(tUrl, tTileData);
  28:     }
  29:     else
  30:     {
  31:         MessageBox.Show("the PeriodicTask already existed!!");
  32:     }
  33: }

  c-2. 撰寫在畫面啟動時,自動取得指定的ScheduledAction,並且Bind到畫面的元件;

 

   1: // Constructor
   2: public MainPage()
   3: {
   4:     InitializeComponent();
   5:     
   6:     //搜指定的Scheduled Task Name
   7:     ScheduledAction tTask = ScheduledActionService.Find(PTASKNAME);
   8:     if (tTask != null)
   9:     {
  10:         //行Data binding
  11:         gPeriodicTask = tTask as PeriodicTask;
  12:         PeriodicStackPanel.DataContext = gPeriodicTask;
  13:     }
  14: }

  c-3. 撰寫當點擊Checked = false時,要移除指定的Scheduled Task;

 

   1: private void PeriodicCheckBox_Unchecked(object sender, RoutedEventArgs e)
   2: {
   3:     //移掉PeriodicTask
   4:     ScheduledAction tTask = ScheduledActionService.Find(PTASKNAME);
   5:     if (tTask != null)
   6:         ScheduledActionService.Remove(PTASKNAME);
   7: }

  d. 測試流程

 

  d-1. 開啟程式,點擊「Start Periodic Agent , Create Tile」;

 

  d-2. 建立Tile後,重新點擊程式即可以看到Periodic Agent的狀態;

 

  d-3. 按Start回到Start Page注意Tile的background content與title由null為有值;

 

  如:

 

 

 

 

源碼下載

 

 

 

  以上是分享撰寫Background Schedule Task的應用,這個Agent讓App可以向系統冊一些定期要產生的訊息,那也有在XDA上看過有人撰寫相似Schedule Task的應用,它能直接操作畫面中的資料,我是覺得非常厲害的,它用的是Native-Code的方式,讓Schedule Task可以呼叫來擷取畫面資料。但這個方法更詳細的說明,我自己也還沒有非常的搞懂。所以WP7未來更多的API將會使它更符合大家的應用。

 

  本文來自pou的部落格,原文地址:http://www.dotblogs.com.tw/pou/archive/2011/11/27/59664.aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.