與眾不同 windows phone (12) - Background Task(后台任務)之 PeriodicTask(周期任務)和 ResourceIntensiveTask(資源密集型任務)


[索引頁]
[源碼下載]


與眾不同 windows phone (12) - Background Task(后台任務)之 PeriodicTask(周期任務)和 ResourceIntensiveTask(資源密集型任務)



作者:webabcd


介紹
與眾不同 windows phone 7.5 (sdk 7.1) 之后台任務

  • PeriodicTask - 周期任務
  • ResourceIntensiveTask - 資源密集型任務(通常用於手機與電腦同步數據)



示例
演示如何注冊和運行 PeriodicTask 類型的任務和 ResourceIntensiveTask 類型的任務
1、后台代理
MyScheduledTaskAgent/ScheduledAgent.cs

/*
 * 本例演示如何由后台任務定時彈出 Toast,以及如何定時更新應用程序瓷磚的 Badge 
 * 建議使用 ScheduledTaskAgent 類型的模板創建此項目
 * 
 * BackgroundAgent - 后台代理類,抽象類,它是 ScheduledTaskAgent、AudioPlayerAgent 和 AudioStreamingAgent 的基類
 *     NotifyComplete() - 用於通知系統,代理已經完成了當前的任務,調用此方法后,系統才會去准備執行下一次任務
 *     Abort() - 用於通知系統,放棄此次和以后的任務,對應的 ScheduledAction 的 IsScheduled 將變為 false
 *     
 * ScheduledTaskAgent - 后台計划任務代理類,抽象類
 *     OnInvoke(ScheduledTask task) - 后台任務每次執行時都會調用此方法
 *     
 * ScheduledAgent - 用於演示后台任務的類,繼承自 ScheduledTaskAgent,需要重寫 ScheduledTaskAgent 的 OnInvoke() 方法
 *     
 * DeviceStatus.ApplicationMemoryUsageLimit - 程序在此時被分配到的內存數量(單位:字節),每次獲取此值可能都不一樣,但是肯定不會超過 6MB
 * 
 * ShellToast - 用於管理 Toast
 *     Title - Toast 的標題
 *     Content - Toast 的內容
 *     NavigationUri - 單擊 Toast 之后鏈接到的目標地址(Uri 類型)
 *     Show() - 顯示 Toast(注:如果 Show 方法的調用程序正在前台運行,則不會顯示 Toast)
 *     
 * ScheduledActionService.LaunchForTest(string name, TimeSpan delay)
 *     對於 ScheduledTask 類型的任務,在指定的時間后馬上執行任務。其用於開發目的,僅在開發工具部署的應用程序中有效
 *     PeriodicTask 和 ResourceIntensiveTask 均繼承自 ScheduledTask
 */

using System.Windows;
using Microsoft.Phone.Scheduler;

using Microsoft.Phone.Shell;
using Microsoft.Phone.Info;
using System;
using System.Linq;

namespace MyScheduledTaskAgent
{
    public class ScheduledAgent : ScheduledTaskAgent
    {
        /*
         * _classInitialized - 用於標記 ScheduledAgent 是否已經被初始化
         *     標記成 volatile 是為了避免編譯器認為此字段無外部修改,而將其優化放入寄存器(標記成 volatile 的字段只會放在內存中)
         *     一般來說,多任務環境下各任務間共享的字段應該被標記為 volatile
         */
        private static volatile bool _classInitialized;

        public ScheduledAgent()
        {
            if (!_classInitialized)
            {
                _classInitialized = true;

                Deployment.Current.Dispatcher.BeginInvoke(delegate
                {
                    Application.Current.UnhandledException += ScheduledAgent_UnhandledException;
                });
            }
        }
        private void ScheduledAgent_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                System.Diagnostics.Debugger.Break();
            }
        }

        protected override void OnInvoke(ScheduledTask task)
        {
            string toastTitle = "";

            if (task is PeriodicTask)
                toastTitle = "PeriodicTask";
            else if (task is ResourceIntensiveTask)
                toastTitle = "ResourceIntensiveTask";

            string toastContent = "MemoryUsageLimit: " + DeviceStatus.ApplicationMemoryUsageLimit;

            // 彈出 Toast
            ShellToast toast = new ShellToast();
            toast.Title = toastTitle;
            toast.Content = toastContent;
            toast.NavigationUri = new Uri("/BackgroundTask/BackgroundAgentDemo.xaml?param=abc&param2=xyz", UriKind.Relative);
            toast.Show();

            // 更新應用程序磁貼的 Badge
            ShellTile applicationTile = ShellTile.ActiveTiles.First();
            StandardTileData newTile = new StandardTileData
            {
                Count = new Random().Next(1, 99)
            };
            applicationTile.Update(newTile);

#if DEBUG
            // 15 秒后執行“task.Name”任務
            ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(15));
#endif

            NotifyComplete();
        }
    }
}

/*
 * 主程序引用此項目后,會在 manifest 中添加如下信息:
 * <ExtendedTask Name="BackgroundTask">
 * <BackgroundServiceAgent Specifier="ScheduledTaskAgent" Name="MyScheduledTaskAgent" Source="MyScheduledTaskAgent" Type="MyScheduledTaskAgent.ScheduledAgent" />
 * </ExtendedTask>
 */


2、前台注冊指定的后台代理
BackgroundAgentDemo.xaml

<phone:PhoneApplicationPage 
    x:Class="Demo.BackgroundTask.BackgroundAgentDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
    shell:SystemTray.IsVisible="True">

    <StackPanel Orientation="Vertical">

        <Button Name="btnStartPeriodicTask" Content="Start Periodic Task Agent" Click="btnStartPeriodicTask_Click" />
        <Button Name="btnStartResourceIntensiveTask" Content="Start Resource Intensive Task Agent" Click="btnStartResourceIntensiveTask_Click" />

        <TextBlock x:Name="lblMsg" />
        
    </StackPanel>
    
</phone:PhoneApplicationPage>

BackgroundAgentDemo.xaml.cs

/*
 * 本例演示:如何注冊 PeriodicTask 類型的任務和 ResourceIntensiveTask 類型的任務
 * 
 * ScheduledAction - 所有計划活動的基類,抽象類。ScheduledNotification 和 ScheduledTask 繼承自此類
 *     Name - ScheduledAction 的名稱,此名稱即 ID
 * ScheduledTask - 計划任務類,抽象類。PeriodicTask 和 ResourceIntensiveTask 繼承自此類
 *     Description - 針對后台任務的描述,將顯示在 設置->應用程序-后台任務 中
 *     支持及不支持的 api 參見:http://msdn.microsoft.com/en-us/library/hh202962(v=vs.92)
 *     內存使用的上限值為 6MB,具體上限值從 ApplicationMemoryUsageLimit 獲取(根據實際情況每次獲取到的值可能都不一樣,但肯定不會超過 6MB)
 *     一個計划任務最多執行兩周,兩周后要重新 ScheduledAction.Add(),每次 ScheduledAction.Add() 之后最多執行兩周
 *     任務連續兩次崩潰之后將會被取消
 * 
 * PeriodicTask - 周期任務
 *     PeriodicTask 每 30 分鍾被執行一次,每次最多持續 25 秒
 * ResourceIntensiveTask - 資源密集型任務(通常用於手機與電腦同步數據)
 *     ResourceIntensiveTask 每次最多持續 10 分鍾
 *     需要使用外部電源,或使用本機電池時電量在 90% 以上
 *     需要 WiFi 或 PC 連接網絡
 *     必須在鎖屏狀態下且無手機呼叫
 * 
 * ScheduledActionService - 管理 ScheduledAction 的類
 *     ScheduledActionService.GetActions<T>() where T : ScheduledAction - 查找系統中已注冊的 ScheduledAction 類型的數據
 *     ScheduledAction.Find(string name) - 按名稱查找指定的 ScheduledAction
 *     ScheduledAction.Remove(string name) - 按名稱刪除指定的 ScheduledAction
 *     ScheduledAction.Add(ScheduledAction action) - 注冊一個新的 ScheduledAction
 *     ScheduledAction.Replace(ScheduledAction action) - 更新指定的 ScheduledAction
 *     ScheduledActionService.LaunchForTest(string name, TimeSpan delay) - 對於 ScheduledTask 類型的任務,在指定的時間后馬上執行任務。其用於開發目的,僅在開發工具部署的應用程序中有效
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

using Microsoft.Phone.Scheduler;

namespace Demo.BackgroundTask
{
    public partial class BackgroundAgentDemo : PhoneApplicationPage
    {
        private PeriodicTask _periodicTask;
        private string _periodicTaskName = "PeriodicTask";

        private ResourceIntensiveTask _resourceIntensiveTask;
        private string _resourceIntensiveTaskName = "ResourceIntensiveTask";

        public BackgroundAgentDemo()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            if (NavigationContext.QueryString.Count > 0)
            {
                lblMsg.Text = "參數 param 的值為:" + this.NavigationContext.QueryString["param"];
                lblMsg.Text += Environment.NewLine;
                lblMsg.Text += "參數 param2 的值為:" + this.NavigationContext.QueryString["param2"];
            }

            base.OnNavigatedTo(e);
        }

        private void btnStartPeriodicTask_Click(object sender, RoutedEventArgs e)
        {
            // 實例化一個新的 PeriodicTask
            _periodicTask = ScheduledActionService.Find(_periodicTaskName) as PeriodicTask;
            if (_periodicTask != null)
                ScheduledActionService.Remove(_periodicTaskName);
            _periodicTask = new PeriodicTask(_periodicTaskName);

            _periodicTask.Description = "用於演示 PeriodicTask";

            try
            {
                // 每次都注冊一個新的 PeriodicTask,以最大限度避免兩周后無法執行的問題
                ScheduledActionService.Add(_periodicTask);
#if DEBUG
                // 1 秒后執行任務
                ScheduledActionService.LaunchForTest(_periodicTaskName, TimeSpan.FromSeconds(1));
#endif
            }
            catch (InvalidOperationException exception)
            {
                if (exception.Message.Contains("BNS Error: The action is disabled"))
                {
                    // 代理已被禁用
                }
                if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added."))
                {
                    // 代理的數量超過了設備的限制(設備的最大代理數是由設備進行硬性限制的,最低值是 6)
                }
            }
            catch (Exception ex)
            {

            }
        }

        private void btnStartResourceIntensiveTask_Click(object sender, RoutedEventArgs e)
        {
            // 實例化一個新的 ResourceIntensiveTask
            _resourceIntensiveTask = ScheduledActionService.Find(_resourceIntensiveTaskName) as ResourceIntensiveTask;
            if (_resourceIntensiveTask != null)
                ScheduledActionService.Remove(_resourceIntensiveTaskName);
            _resourceIntensiveTask = new ResourceIntensiveTask(_resourceIntensiveTaskName);

            _resourceIntensiveTask.Description = "用於演示 ResourceIntensiveTask";

            try
            {
                // 每次都注冊一個新的 ResourceIntensiveTask,以最大限度避免兩周后無法執行的問題
                ScheduledActionService.Add(_resourceIntensiveTask);
#if DEBUG
                // 1 秒后執行任務
                ScheduledActionService.LaunchForTest(_resourceIntensiveTaskName, TimeSpan.FromSeconds(1));
#endif
            }
            catch (InvalidOperationException exception)
            {
                if (exception.Message.Contains("BNS Error: The action is disabled"))
                {
                    // 代理已被禁用
                }
                if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added."))
                {
                    // 代理的數量超過了設備的限制(設備的最大代理數是由設備進行硬性限制的,最低值是 6)
                }
            }
            catch (Exception ex)
            {

            }
        }
    }
}



OK
[源碼下載]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM