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

技术标签: ui  操作系统  

原文: 重新想象 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
[源码下载]

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_33915554/article/details/85658001

智能推荐

【九度】题目1090:路径打印 && 【LeetCode】Simplify Path_打印目录结构 leetcode-程序员宅基地

文章浏览阅读1.3k次。1、题目1090:路径打印时间限制:1 秒内存限制:32 兆特殊判题:否提交:1319解决:230题目描述:给你一串路径,譬如:a\b\ca\d\eb\cstd\你把这些路径中蕴含的目录结构给画出来,子目录直接列在父目录下面,并比父目录向右缩一格,就像这样:a b c d eb cstd同一级的需要按字母顺序_打印目录结构 leetcode

如何使用Cordova将SAP Fiori应用打包并安装到Android平台上_fiori发布安卓-程序员宅基地

文章浏览阅读591次。There is a wonderful tutorial Building SAP Fiori-like UIs with SAPUI5 in 10 Exercises written by Bertram Ganz.In this blog, I will show step by step how to package the UI5 application built by this tutorial as a native application into your Android device_fiori发布安卓

程序员代码面试指南下(7-9)-程序员宅基地

文章浏览阅读182次。目录第7章 1 不用额外变量交换两个整数的值(士 ★☆☆☆) 2 不用任何比较判断找出两个数中较大的数(校★★★☆) 3 只用位运算不用算术运算实现整数的加减乘除运算 4 整数的二进制表达中有多少个1 5 在其他数都出现偶数次的数组中找到出现奇数次的数 6 在其他数都出现A次的数组中找到只出现一次的数第8章 1 转圈打印矩阵 2 将正方形矩阵顺时针转动90度 3 之..._if (map.containskey(xor)) { int pre = map.get(xor); mosts[i] = pre =

uva-1399 Puzzle-程序员宅基地

文章浏览阅读152次。AC自动机上的dp

C++中 sprintf函数的用法_sprintf %c-程序员宅基地

文章浏览阅读871次。C++中 sprintf函数的用法1.常用方式sprintf函数的功能与printf函数的功能基本一样,只是它把结果输出到指定的字符串中了,看个例子就明白了:例:将”test 1 2”写入数组s中#include&lt;stdio.h&gt;int main(int argc, char *avgv[]){ char s[40]; sprintf(s,"%s%d..._sprintf %c

Java开发的医院门诊挂号系统_医院预约挂号er图-程序员宅基地

文章浏览阅读2.2k次。医院门诊系统,挂号预约系统,有四个角色(管理员,医生,护士,普通用户)_医院预约挂号er图

随便推点

Android Socket Demo [ 附客户端与服务端源码 ]_android socket客户端下载-程序员宅基地

文章浏览阅读818次。如果要跑通demo首先: 服务端我是用 intellij idea 开发的。如果用其他软件打跑不起来就用 intellij其次: 要将手机跟电脑连在同个网络下最后: Constants的ip地址要填写上电脑的ip地址实现功能:客户端连接服务端,客户端发数据到服务端,客户端收到服务端发来的数据服务端收到客户端发的数据,服务端发数据给客户端贴部分核心代码客户端连接服务端:首先客户端连接服务端必须要在线程里(后面的是 ip地址 跟端口,端口是服务端的socke..._android socket客户端下载

定制win10桌面_win10联想 自带主题-程序员宅基地

文章浏览阅读1.3k次,点赞4次,收藏7次。壁纸在文末先上几张美化后的照片 主题链接win 10 美化相信很多人都厌倦了win10原装主题了,陈旧的窗口边框,一如既往的图标,老掉牙的窗口样式和菜单栏……算了,就不吐槽了,直接上教程吧!前方高能第零步关掉杀毒软件(新手建议卸载),这点非常重要,如某数字,某讯,某霸,如果关掉以后放心不下自己电脑的安全,以下文章请勿食用!(后果自负)第一步破解原装win10系统主题。友..._win10联想 自带主题

jQuery懒加载插件 – jquery.lazyload.js简单调用-程序员宅基地

文章浏览阅读57次。 Lazy Load 是一个用 JavaScript 编写的 jQuery 插件. 它可以延迟加载长页面中的图片. 在浏览器可视区域外的图片不会被载入, 直到用户将页面滚动到它们所在的位置. 这与图片预加载的处理方式正好是相反的.在包含很多大图片长页面中延迟加载图片可以加快页面加载速度. 浏览器将会在加载可见图片之后即进入就绪状态. 在某些情况下还可以帮助降低服务器负担。一、下载和引用  ..._jq.lazyload.js配置

mysql_172.25.2.1-程序员宅基地

文章浏览阅读404次。一.cmake升级https://cmake.org/download/ #cmake下载地址 yum install jsoncpp-0.10.5-2.el7.x86_64.rpm jsoncpp-devel-0.10.5-2.el7.x86_64.rpm -y yum install cmake3-3.6.1-2.el7.x86_64.rpm cmake3-data-3.6.1-2.el7.noarch.rpm -y二.mysql编译安装升级gcctar zxf mysql-boost-_172.25.2.1

基于Numpy的线性代数运算_numpy线性代数运算-程序员宅基地

文章浏览阅读737次。标题中的英文首字母大写比较规范,但在python实际使用中均为小写。1.Numpy中的matrix1.1 创建matrix对象numpy.matrix方法的参数可以为ndarray对象numpy.matrix方法的参数也可以为字符串str,示例如下:import numpy as npm = np.matrix("1 2 3;4 5 6; 7 ..._numpy线性代数运算

搭建LAMP环境(源码方式)_this software is subject to the php license, avail-程序员宅基地

文章浏览阅读3.7k次。源码方式,搭建LAMP环境。_this software is subject to the php license, available in this | | distribut