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

目录
相关文章
用MASM32按Time Protocol(RFC868)协议编写网络对时程序中的一些有用的函数代码
用MASM32按Time Protocol(RFC868)协议编写网络对时程序中的一些有用的函数代码
|
3月前
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
16天前
|
C# Windows
【Azure App Service】在App Service for Windows上验证能占用的内存最大值
根据以上测验,当使用App Service内存没有达到预期的值,且应用异常日志出现OutOfMemory时,就需要检查Platform的设置是否位64bit。
39 11
|
2月前
|
Windows Python
python获取windows机子上运行的程序名称
python获取windows机子上运行的程序名称
|
2月前
|
安全 Windows
怎样利用 Windows XP实现网络统一关机
怎样利用 Windows XP实现网络统一关机
怎样利用 Windows XP实现网络统一关机
|
1月前
|
缓存 开发框架 移动开发
uni-app:下载使用uni&创建项目&和小程序链接&数据缓存&小程序打包 (一)
uni-app 是一个跨平台的开发框架,它允许开发者使用 Vue.js 来构建应用程序,并能够同时发布到多个平台,如微信小程序、支付宝小程序、H5、App(通过DCloud的打包服务)等。uni-app 的目标是通过统一的代码库,简化多平台开发过程,提高开发效率。 在这一部分中,我们将逐步介绍如何下载和使用uni-app、创建一个新的项目、如何将项目链接到小程序,以及实现数据缓存的基本方法。
|
1月前
|
安全 API C#
C# 如何让程序后台进程不被Windows任务管理器强制结束
C# 如何让程序后台进程不被Windows任务管理器强制结束
65 0
|
1月前
|
安全 网络协议 IDE
使用Python编写网络扫描程序
使用Python编写网络扫描程序
|
2月前
|
安全 网络安全 API
基于WMI更新Windows系统信息采集程序sysInfo的一些收获
基于WMI更新Windows系统信息采集程序sysInfo的一些收获
|
2月前
|
小程序 Windows
MASM32编写的程序在Windows 7,10下运行正常,但在Win XP下运行时只闻其声不见其形的故障
MASM32编写的程序在Windows 7,10下运行正常,但在Win XP下运行时只闻其声不见其形的故障
下一篇
无影云桌面