重新想象 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().InnerText = "所有任务全部执行成功";
ToastNotification successToast = new ToastNotification(successToastXml);
backgroundDownloader.SuccessToastNotification = successToast; // 设置 FailureToastNotification
XmlDocument failureToastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
failureToastXml.GetElementsByTagName("text").Item().InnerText = "至少有一个下载任务失败了";
ToastNotification failureToast = new ToastNotification(failureToastXml);
backgroundDownloader.FailureToastNotification = failureToast; // 设置 SuccessTileNotification
XmlDocument successTileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Text03);
XmlNodeList successTextNodes = successTileXml.GetElementsByTagName("text");
successTextNodes.Item().InnerText = "所有";
successTextNodes.Item().InnerText = "任务";
successTextNodes.Item().InnerText = "全部";
successTextNodes.Item().InnerText = "成功";
TileNotification successTile = new TileNotification(successTileXml);
successTile.ExpirationTime = DateTime.Now.AddMinutes();
backgroundDownloader.SuccessTileNotification = successTile; // 设置 FailureTileNotification
XmlDocument failureTileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Text03);
XmlNodeList failureTextNodes = failureTileXml.GetElementsByTagName("text");
failureTextNodes.Item().InnerText = "至少";
failureTextNodes.Item().InnerText = "一个";
failureTextNodes.Item().InnerText = "任务";
failureTextNodes.Item().InnerText = "失败";
TileNotification failureTile = new TileNotification(failureTileXml);
failureTile.ExpirationTime = DateTime.Now.AddMinutes();
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
[源码下载]
重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性的更多相关文章
- 重新想象 Windows 8.1 Store Apps 系列文章索引
[源码下载] [重新想象 Windows 8 Store Apps 系列文章] 重新想象 Windows 8.1 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...
- 重新想象 Windows 8.1 Store Apps (81) - 控件增强: WebView 之加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Contract 分享 WebView 中的内容, 为 WebView 截图
[源码下载] 重新想象 Windows 8.1 Store Apps (81) - 控件增强: WebView 之加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Co ...
- 重新想象 Windows 8.1 Store Apps (72) - 新增控件: AppBar, CommandBar
[源码下载] 重新想象 Windows 8.1 Store Apps (72) - 新增控件: AppBar, CommandBar 作者:webabcd 介绍重新想象 Windows 8.1 Sto ...
- 重新想象 Windows 8.1 Store Apps (73) - 新增控件: DatePicker, TimePicker
[源码下载] 重新想象 Windows 8.1 Store Apps (73) - 新增控件: DatePicker, TimePicker 作者:webabcd 介绍重新想象 Windows 8.1 ...
- 重新想象 Windows 8.1 Store Apps (74) - 新增控件: Flyout, MenuFlyout, SettingsFlyout
[源码下载] 重新想象 Windows 8.1 Store Apps (74) - 新增控件: Flyout, MenuFlyout, SettingsFlyout 作者:webabcd 介绍重新想象 ...
- 重新想象 Windows 8.1 Store Apps (75) - 新增控件: Hub, Hyperlink
[源码下载] 重新想象 Windows 8.1 Store Apps (75) - 新增控件: Hub, Hyperlink 作者:webabcd 介绍重新想象 Windows 8.1 Store A ...
- 重新想象 Windows 8.1 Store Apps (76) - 新增控件: SearchBox
[源码下载] 重新想象 Windows 8.1 Store Apps (76) - 新增控件: SearchBox 作者:webabcd 介绍重新想象 Windows 8.1 Store Apps 之 ...
- 重新想象 Windows 8.1 Store Apps (77) - 控件增强: 文本类控件的增强, 部分控件增加了 Header 属性和 HeaderTemplate 属性, 部分控件增加了 PlaceholderText 属性
[源码下载] 重新想象 Windows 8.1 Store Apps (77) - 控件增强: 文本类控件的增强, 部分控件增加了 Header 属性和 HeaderTemplate 属性, 部分控件 ...
- 重新想象 Windows 8.1 Store Apps (78) - 控件增强: ScrollViewer, FlipView, Popup
[源码下载] 重新想象 Windows 8.1 Store Apps (78) - 控件增强: ScrollViewer, FlipView, Popup 作者:webabcd 介绍重新想象 Wind ...
随机推荐
- Gson 和 FastJson 性能测试
使用版本: compile 'com.google.code.gson:gson:2.7' compile 'com.alibaba:fastjson:1.2.17' 评测样板为一个People数组, ...
- Kafka - SQL 引擎分享
1.概述 大多数情况下,我们使用 Kafka 只是作为消息处理.在有些情况下,我们需要多次读取 Kafka 集群中的数据.当然,我们可以通过调用 Kafka 的 API 来完成,但是针对不同的业务需求 ...
- 如何查看 exec sp_execute 10 XXX, XXXX的RPC事件 内容
使用事件探查器经常能捕捉到类似于exec sp_execute 10 XXX, XXXX的RPC事件. 我想问下从哪里可以看到存储过程sp_execute 10的内容呢?? 方法如下: 在新建的pro ...
- Emit动态生成代码
Emit动态生成代码 引用:秒懂C#通过Emit动态生成代码 首先需要声明一个程序集名称, // specify a new assembly name var assemblyName = new ...
- MFC中混合使用Duilib制作界面
因为公司项目最近入了MFC的这个大坑,用MFC做UI做了一段时间,感觉不是很方便,开发效率有点慢. 看了c++里面做界面的类库,感觉Duilib比较符合做界面的需求,而且很多大公司也在使用Duilib ...
- [转]android开发之字节顺序
原文在此 android上C++程序为小端字节顺序,和windows上一样. 而android上的JAVA程序则使用的是大端字节顺序. 用NDK和java SDK 做android程序时发现的问题,记 ...
- Swift 集合类型
Swift语言提供数组和字典的集合类型 Swift 语言里的数组和字典中存储的数据值类型必须明确 ,即数组中只能存放同类型的数据. 1: 数组 数组的创建 var shoppingList: St ...
- Codeforces Round #237 (Div. 2) C. Restore Graph(水构造)
题目大意 一个含有 n 个顶点的无向图,顶点编号为 1~n.给出一个距离数组:d[i] 表示顶点 i 距离图中某个定点的最短距离.这个图有个限制:每个点的度不能超过 k 现在,请构造一个这样的无向图, ...
- #ifdef 和 #if defined 的区别 -- 转
#ifdef 和 #if defined 的区别在于,后者可以组成复杂的预编译条件,比如 #if defined (AAA) && defined (BBB) xxxxxxxxx #e ...
- Python——目录操作
注意之前要import os 1.获得当前路径 在Python中可以使用os.getcwd()函数获得当前的路径.其原型如下所示. os.getcwd() 该函数不需要传递参数,它返回当前的目录.需要 ...