重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性

简介: 原文:重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性[源码下载] 重新想象 Windows 8.
原文: 重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性

[源码下载]


重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性



作者:webabcd


介绍
重新想象 Windows 8.1 Store Apps 之后台任务的新特性

  • 下载和上传的新特性
  • 程序启动前预下载网络资源
  • 后台任务的其它新特性



示例
1、本例用于说明 win8.1 中后台下载和上传的新特性(本例用后台下载说明,后台上传与此类似)
TransferNew.xaml

<Page
    x:Class="Windows81.BackgroundTask.TransferNew"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows81.BackgroundTask"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">

            <ScrollViewer Height="100">
                <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" />
            </ScrollViewer>

            <Button Name="btnDownload" Content="后台下载文件" Margin="0 10 0 0" Click="btnDownload_Click" />

        </StackPanel>
    </Grid>
</Page>

TransferNew.xaml.cs

/*
 * 本例用于说明 win8.1 中后台下载和上传的新特性(本例用后台下载说明,后台上传与此类似)
 * 以下仅列出新增的功能,关于上传和下载的基础请参见:http://www.cnblogs.com/webabcd/archive/2013/10/21/3379890.html
 * 
 * 
 * BackgroundTransferGroup - 用于分组传输任务,可以指定此分组中的传输任务是并行的还是串行的
 *     static CreateGroup(string name) - 创建一个指定名字的传输分组,此名字需要是全系统唯一的,建议用 guid
 *     Name - 传输分组的名字
 *     TransferBehavior - 传输行为(BackgroundTransferBehavior 枚举:Parallel 或 Serialized)
 * 
 * BackgroundDownloader - 后台下载任务管理器
 *     static GetCurrentDownloadsForTransferGroupAsync(BackgroundTransferGroup group) - 获取指定传输分组下的所有下载任务(BackgroundTransferGroup 是 win8.1 新增的概念,但是仍然保留了原来 win8 里的 Group 的概念)
 *     TransferGroup - 指定此下载任务管理器的 BackgroundTransferGroup
 *     SuccessToastNotification - 此下载任务管理器中的所有传输任务均成功之后调用的 toast 通知
 *     FailureToastNotification - 有传输任务失败后调用的 toast 通知
 *     SuccessTileNotification - 此下载任务管理器中的所有传输任务均成功之后调用的 tile 通知
 *     FailureTileNotification - 有传输任务失败后调用的 tile 通知
 *     static RequestUnconstrainedDownloadsAsync(IEnumerable<DownloadOperation> operations) - 告诉系统,希望指定的下载任务是无约束的(返回一个 UnconstrainedTransferRequestResult 对象)
 *     
 * UnconstrainedTransferRequestResult - 向系统请求无约束下载时,系统返回的结果
 *     IsUnconstrained - 系统是否允许你指定的下载任务是无约束的(所谓无约束就是不存在当设备依靠电池运行时通常与后台网络操作相关联的资源限制)
 *     
 * DownloadOperation - 下载任务对象
 *     Priority - 下载任务的优先级(BackgroundTransferPriority 枚举:Default 或 High)
 */

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Windows.Data.Xml.Dom;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.UI.Notifications;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Web;

namespace Windows81.BackgroundTask
{
    public sealed partial class TransferNew : Page
    {
        private BackgroundTransferGroup _transferGroup;

        public TransferNew()
        {
            this.InitializeComponent();
        }

        // 后台下载一个文件
        private async void btnDownload_Click(object sender, RoutedEventArgs e)
        {
            // 下载地址(注意需要在 Package.appxmanifest 中增加对 .rar 类型文件的关联)
            Uri sourceUri = new Uri("http://files.cnblogs.com/webabcd/Windows8.rar", UriKind.Absolute);

            StorageFile destinationFile;
            try
            {
                // 保存的目标地址
                destinationFile = await KnownFolders.DocumentsLibrary.CreateFileAsync("Windows8.rar", CreationCollisionOption.GenerateUniqueName);
            }
            catch (Exception ex)
            {
                lblMsg.Text += ex.ToString();
                lblMsg.Text += Environment.NewLine;
                return;
            }

            // 创建一个后台下载任务管理器
            BackgroundDownloader backgroundDownloader = new BackgroundDownloader();


            // 创建一个传输分组,并指定此分组中的传输任务是并行的还是串行的
            _transferGroup = BackgroundTransferGroup.CreateGroup("webabcdBackground");
            _transferGroup.TransferBehavior = BackgroundTransferBehavior.Parallel;
            backgroundDownloader.TransferGroup = _transferGroup;


            // 设置 SuccessToastNotification
            XmlDocument successToastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
            successToastXml.GetElementsByTagName("text").Item(0).InnerText = "所有任务全部执行成功";
            ToastNotification successToast = new ToastNotification(successToastXml);
            backgroundDownloader.SuccessToastNotification = successToast;

            // 设置 FailureToastNotification
            XmlDocument failureToastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
            failureToastXml.GetElementsByTagName("text").Item(0).InnerText = "至少有一个下载任务失败了";
            ToastNotification failureToast = new ToastNotification(failureToastXml);
            backgroundDownloader.FailureToastNotification = failureToast;


            // 设置 SuccessTileNotification
            XmlDocument successTileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Text03);
            XmlNodeList successTextNodes = successTileXml.GetElementsByTagName("text");
            successTextNodes.Item(0).InnerText = "所有";
            successTextNodes.Item(1).InnerText = "任务";
            successTextNodes.Item(2).InnerText = "全部";
            successTextNodes.Item(3).InnerText = "成功";
            TileNotification successTile = new TileNotification(successTileXml);
            successTile.ExpirationTime = DateTime.Now.AddMinutes(10);
            backgroundDownloader.SuccessTileNotification = successTile;

            // 设置 FailureTileNotification
            XmlDocument failureTileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Text03);
            XmlNodeList failureTextNodes = failureTileXml.GetElementsByTagName("text");
            failureTextNodes.Item(0).InnerText = "至少";
            failureTextNodes.Item(1).InnerText = "一个";
            failureTextNodes.Item(2).InnerText = "任务";
            failureTextNodes.Item(3).InnerText = "失败";
            TileNotification failureTile = new TileNotification(failureTileXml);
            failureTile.ExpirationTime = DateTime.Now.AddMinutes(10);
            backgroundDownloader.FailureTileNotification = failureTile;


            // 创建一个下载任务,并指定其优先级
            DownloadOperation download = backgroundDownloader.CreateDownload(sourceUri, destinationFile);
            download.Priority = BackgroundTransferPriority.High;


            // 向系统请求,将指定的下载任务设置为无约束下载
            List<DownloadOperation> requestOperations = new List<DownloadOperation>();
            requestOperations.Add(download);
            UnconstrainedTransferRequestResult result = await BackgroundDownloader.RequestUnconstrainedDownloadsAsync(requestOperations);


            // 监视指定的后台下载任务
            await HandleDownloadAsync(download);
        }


        /// <summary>
        /// 监视指定的后台下载任务
        /// </summary>
        /// <param name="download">后台下载任务</param>
        private async Task HandleDownloadAsync(DownloadOperation download)
        {
            try
            {
                lblMsg.Text = "start";

                // 当下载进度发生变化时的回调函数
                Progress<DownloadOperation> progressCallback = new Progress<DownloadOperation>(DownloadProgress);

                // 所有下载任务的关联的 CancellationTokenSource 对象(这个最好摘出来,因为不用的时候最好手工 Dispose 掉)
                CancellationTokenSource _cancelToken = new CancellationTokenSource(); 
                await download.StartAsync().AsTask(_cancelToken.Token, progressCallback); // 新增一个后台下载任务

                // 下载完成后获取服务端的响应信息
                ResponseInformation response = download.GetResponseInformation();
                lblMsg.Text += "Completed: " + response.ActualUri + "-" + response.StatusCode.ToString();
                lblMsg.Text += Environment.NewLine;
            }
            catch (TaskCanceledException) // 调用 CancellationTokenSource.Cancel() 后会抛出此异常
            {
                lblMsg.Text += "Canceled: " + download.Guid;
                lblMsg.Text += Environment.NewLine;
            }
            catch (Exception ex)
            {
                // 将异常转换为 WebErrorStatus 枚举,如果获取到的是 WebErrorStatus.Unknown 则说明此次异常不是涉及 web 的异常
                WebErrorStatus error = BackgroundTransferError.GetStatus(ex.HResult);

                lblMsg.Text += ex.ToString();
                lblMsg.Text += Environment.NewLine;
            }
            finally
            {
               
            }
        }

        // 进度发生变化时,显示最新的进度信息
        private void DownloadProgress(DownloadOperation download)
        {
            lblMsg.Text = download.Progress.BytesReceived.ToString("#,0") + " / " + download.Progress.TotalBytesToReceive.ToString("#,0");
        }
    }
}


2、演示如何对指定 web 资源预下载(系统会尝试在用户启动 app 之前下载指定的资源,也就是说不管 app 是否打开,系统都会在其觉得合适的时候对指定的资源做预下载)
ContentPrefetcher.xaml

<Page
    x:Class="Windows81.BackgroundTask.ContentPrefetcher"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows81.BackgroundTask"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">

            <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" />

            <Button Name="btnAddContentPrefetcher" Content="添加一个“预下载”任务" Click="btnAddContentPrefetcher_Click" Margin="0 10 0 0" />

            <StackPanel Name="pnlStatus" Margin="0 10 0 0" />

        </StackPanel>
    </Grid>
</Page>

ContentPrefetcher.xaml.cs

/*
 * ContentPrefetcher - 对指定 web 资源预下载(系统会尝试在用户启动 app 之前下载指定的资源,也就是说不管 app 是否打开,系统都会在其觉得合适的时候对指定的资源做预下载)
 *     ContentUris - 需要加入到“预下载”的 uri
 *     IndirectContentUri - 指定一个远程 xml 地址,此 xml 用于描述需要“预下载”的资源列表,格式如下
 *         <?xml version="1.0" encoding="utf-8"?>
 *         <prefetchUris>
 *             <uri>http://www.w1.com</uri>
 *             <uri>http://www.w2.com</uri>
 *             <uri>http://www.w3.com</uri>
 *         </prefetchUris>
 *     LastSuccessfulPrefetchTime - 最近一次成功地预下载的时间
 */

using System;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Windows81.BackgroundTask
{
    public sealed partial class ContentPrefetcher : Page
    {
        public ContentPrefetcher()
        {
            this.InitializeComponent();

            UpdateStatus();
        }

        private void btnAddContentPrefetcher_Click(object sender, RoutedEventArgs e)
        {
            // 向预下载中心增加一个预下载任务
            Windows.Networking.BackgroundTransfer.ContentPrefetcher.ContentUris.Add(new Uri("http://www.baidu.com"));

            // 清空预下载任务
            // Windows.Networking.BackgroundTransfer.ContentPrefetcher.ContentUris.Clear();
            
            // 更新状态
            UpdateStatus();
        }

        private async void UpdateStatus()
        {
            pnlStatus.Children.Clear();

            foreach (Uri uri in Windows.Networking.BackgroundTransfer.ContentPrefetcher.ContentUris)
            {
                string url = uri.ToString();
                bool cached = await CheckStatus(uri);

                pnlStatus.Children.Add(new TextBlock() { Text = url + " - " + cached.ToString() });
            }

            DateTimeOffset? lastPrefetchTime = Windows.Networking.BackgroundTransfer.ContentPrefetcher.LastSuccessfulPrefetchTime;
            if (lastPrefetchTime != null)
            {
                lblMsg.Text = "最近一次成功地“预下载”了内容的时间是:" + lastPrefetchTime.Value.ToString("yyyy-MM-dd hh:mm:ss");
            }
            else
            {
                lblMsg.Text = "还没有“预下载”成功过";
            }
        }

        private async Task<bool> CheckStatus(Uri uri)
        {
            // 只从本地缓存加载指定的 http 资源
            var filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
            filter.CacheControl.ReadBehavior = Windows.Web.Http.Filters.HttpCacheReadBehavior.OnlyFromCache;

            var httpClient = new Windows.Web.Http.HttpClient(filter);
            var request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Get, uri);

            try
            {
                // 指定的资源在本地有缓存
                await httpClient.SendRequestAsync(request);
                return true;
            }
            catch
            {
                // 指定的资源在本地无缓存
                return false;
            }
        }
    }
}


3、演示后台任务的其它新特性
Other.xaml

<Page
    x:Class="Windows81.BackgroundTask.Other"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows81.BackgroundTask"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">

            <TextBlock Name="lblMsg" FontSize="14.667" Margin="0 10 0 0" Text="详见 .cs 中的代码注释" />

        </StackPanel>
    </Grid>
</Page>

Other.xaml.cs

/*
 * win 8.1 中与后台任务相关的其它新特性:
 * 1、在“设置”->“搜索和应用”->“通知”->“免打扰时间”中可以设置免打扰时间
 * 2、免打扰时间内,所有后台任务均暂停,免打扰时间过后,后台任务将随机在不同时间点启动
 * 3、免打扰时间允许两种例外:来电和闹钟
 * 4、后台任务 IBackgroundTaskInstance.Canceled 如果 5 秒内没有完成,则系统会终止该应用,并生成错误报告上传至 windows 商店的开发人员账户
 * 5、Windows.ApplicationModel.Background.BackgroundWorkCost.CurrentBackgroundWorkCost 当前后台任务的开销(BackgroundWorkCostValue 枚举:Low, Medium, High)
 * 6、IBackgroundTaskInstance.SuspendedCount - 由资源管理政策导致后台任务挂起的次数(win8 就支持,之前忘了写了)
 * 
 * 
 * 关于后台任务的基础请参见:http://www.cnblogs.com/webabcd/archive/2013/10/15/3369581.html
 */

using Windows.ApplicationModel.Background;
using Windows.UI.Xaml.Controls;

namespace Windows81.BackgroundTask
{
    public sealed partial class Other : Page
    {
        public Other()
        {
            this.InitializeComponent();
        }
    }
}



OK
[源码下载]

目录
相关文章
|
1月前
|
NoSQL Redis 数据安全/隐私保护
Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
文章提供了Redis最流行的图形化界面工具Another Redis Desktop Manager的下载及使用教程,包括如何下载、解压、连接Redis服务器以及使用控制台和查看数据类型详细信息。
132 6
Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
|
1月前
|
NoSQL Redis 数据库
Redis 图形化界面下载及使用超详细教程(带安装包)! redis windows下客户端下载
文章提供了Redis图形化界面工具的下载及使用教程,包括如何连接本地Redis服务器、操作键值对、查看日志和使用命令行等功能。
124 0
Redis 图形化界面下载及使用超详细教程(带安装包)! redis windows下客户端下载
|
1月前
|
Oracle 关系型数据库 MySQL
Mysql(1)—简介及Windows环境下载安装
MySQL 是一个流行的关系型数据库管理系统(RDBMS),基于 SQL 进行操作。它由瑞典 MySQL AB 公司开发,后被 Sun Microsystems 收购,现为 Oracle 产品。MySQL 是最广泛使用的开源数据库之一,适用于 Web 应用程序、数据仓库和企业应用。
55 2
|
1月前
|
缓存 监控 网络协议
计算机网络的常用的网络通信命令(Windows)
本文介绍了网络技术中常用的命令,如ping用于检测网络连通性,ipconfig查看TCP/IP配置,netstat监控网络状态,arp显示和修改ARP缓存,at安排任务执行,tracert追踪路由,以及nbtstat获取NetBIOS信息。
33 1
|
4天前
|
网络安全 Windows
Windows server 2012R2系统安装远程桌面服务后无法多用户同时登录是什么原因?
【11月更文挑战第15天】本文介绍了在Windows Server 2012 R2中遇到的多用户无法同时登录远程桌面的问题及其解决方法,包括许可模式限制、组策略配置问题、远程桌面服务配置错误以及网络和防火墙问题四个方面的原因分析及对应的解决方案。

热门文章

最新文章