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

目录
相关文章
|
12天前
|
机器学习/深度学习 人工智能 计算机视觉
好的资源-----打卡机+Arm+Qt+OpenCV嵌入式项目-基于人脸识别的考勤系统-----B站神经网络与深度学习,商城
好的资源-----打卡机+Arm+Qt+OpenCV嵌入式项目-基于人脸识别的考勤系统-----B站神经网络与深度学习,商城
|
12天前
|
NoSQL Redis Windows
redis双击闪退解决方法,windows版的redis资源,redis安装,win资源可下
redis双击闪退解决方法,windows版的redis资源,redis安装,win资源可下
网络请求和下载,ping baidu Ctrl + C停掉,wegt命令可以在命令行内下载网络文件
网络请求和下载,ping baidu Ctrl + C停掉,wegt命令可以在命令行内下载网络文件
|
12天前
|
存储 缓存 网络协议
网络编程初学者必备:从零开始的详细教程与资源汇总
网络编程初学者必备:从零开始的详细教程与资源汇总
|
14天前
|
Linux Shell 网络性能优化
Wondershaper网络限制脚本源码分析一(下载速度限制篇)
Wondershaper 是一个简单的 Linux 命令行工具,用于自动管理和控制网络接口的上行和下行带宽,旨在为用户提供稳定的网络体验,尤其是在网络拥塞的情况下。它通过 Traffic Control (tc) 工具集实现这一功能,但与直接使用 tc 相比,Wondersbaper 提供了更简洁易用的界面,特别适合没有深入网络管理知识的用户,但它其实就是由一个bash脚本组成,当然里面的思想非常精华。
|
20天前
|
文字识别 开发工具 Android开发
视觉智能开放平台操作报错合集之使用人脸属性检测接口,出现报错:图片无法下载,请检查链接是否可访问和本地网络情况,该如何解决
在使用视觉智能开放平台时,可能会遇到各种错误和问题。虽然具体的错误代码和消息会因平台而异,但以下是一些常见错误类型及其可能的原因和解决策略的概述,包括但不限于:1. 认证错误、2. 请求参数错误、3. 资源超限、4. 图像质量问题、5. 服务不可用、6. 模型不支持的场景、7. 网络连接问题,这有助于快速定位和解决问题。
|
20天前
|
运维 网络协议 Linux
Linux与Windows下追踪网络路由:traceroute、tracepath与tracert命令详解
Linux与Windows下追踪网络路由:traceroute、tracepath与tracert命令详解
29 0
|
21天前
|
数据采集 JSON 程序员
老程序员分享:Pythonrequests网络数据采集下载视频(ku6)
老程序员分享:Pythonrequests网络数据采集下载视频(ku6)
11 0
|
23天前
|
Windows
解决Windows 11/10 上的网络打印机错误 0x0000011b
解决Windows 11/10 上的网络打印机错误 0x0000011b
32 5
|
25天前
|
安全 Java 网络安全
【认知革命】JAVA网络编程新视角:重新定义URL与URLConnection,让网络资源触手可及!
【6月更文挑战第22天】JAVA网络编程中,URL代表统一资源定位符,用于表示网络资源地址。通过`new URL(&quot;address&quot;)`创建URL对象,可解析和访问其组件。URLConnection是与URL建立连接的接口,用于定制HTTP请求,如设置GET/POST、超时及交换数据。