背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知)
作者:webabcd
介绍
背水一战 Windows 10 之 后台任务
- 后台下载任务(任务分组,并行或串行执行,组完成后通知)
示例
演示后台下载任务的分组,以及如何设置组内任务是并行执行还是串行执行,以及组任务全部完成后如何 toast 或 tile 通知)
BackgroundTask/TransferModel.cs
- /*
- * 扩展了 DownloadOperation 和 UploadOperation,用于 MVVM 绑定数据
- */
- using System;
- using System.ComponentModel;
- using Windows.Networking.BackgroundTransfer;
- namespace Windows10.BackgroundTask
- {
- public class TransferModel : INotifyPropertyChanged
- {
- public DownloadOperation DownloadOperation { get; set; }
- public UploadOperation UploadOperation { get; set; }
- public string Source { get; set; }
- public string Destination { get; set; }
- private string _progress;
- public string Progress
- {
- get { return _progress; }
- set
- {
- _progress = value;
- RaisePropertyChanged("Progress");
- }
- }
- public event PropertyChangedEventHandler PropertyChanged;
- protected void RaisePropertyChanged(string name)
- {
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs(name));
- }
- }
- }
- }
BackgroundTask/TransferGroup.xaml
- <Page
- x:Class="Windows10.BackgroundTask.TransferGroup"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="using:Windows10.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="10 0 10 10">
- <ScrollViewer Name="scrollViewer" Height="100" Margin="5">
- <TextBlock Name="lblMsg" TextWrapping="Wrap" />
- </ScrollViewer>
- <Button Name="btnAddDownload" Content="新增一组(3 个)下载任务,可以指定其是并发还是串行,当这一组的所有任务都完成后弹出通知" Margin="5" Click="btnAddDownload_Click" />
- <Button Name="btnCancel" Content="取消所有下载任务" Margin="5" Click="btnCancel_Click" />
- <ListView Name="listView" Height="286" Padding="5">
- <ListView.ItemTemplate>
- <DataTemplate>
- <StackPanel Margin="0 5" Background="Blue">
- <TextBlock Text="{Binding Source}" Margin="5" />
- <TextBlock Text="{Binding Destination}" Margin="5" />
- <TextBlock Text="{Binding Progress}" Margin="5" />
- </StackPanel>
- </DataTemplate>
- </ListView.ItemTemplate>
- </ListView>
- </StackPanel>
- </Grid>
- </Page>
BackgroundTask/TransferGroup.xaml.cs
- /*
- * 演示后台下载任务的分组,以及如何设置组内任务是并行执行还是串行执行,以及组任务全部完成后如何 toast 或 tile 通知)
- *
- * BackgroundTransferGroup - 后台下载任务的分组对象
- * static BackgroundTransferGroup CreateGroup(string name) - 创建指定分组标识的 BackgroundTransferGroup 对象
- * Name - 分组标识(只读)
- * TransferBehavior - 组内下载任务的执行方式,BackgroundTransferBehavior 枚举
- * Parallel - 并行
- * Serialized - 串行
- *
- * BackgroundDownloader - 后台下载任务管理器
- * TransferGroup - 设置或获取分组对象(BackgroundTransferGroup 类型)
- * static GetCurrentDownloadsForTransferGroupAsync(BackgroundTransferGroup group) - 获取指定组的所有下载任务
- *
- * DownloadOperation - 下载任务对象
- * TransferGroup - 获取此下载任务的分组对象(BackgroundTransferGroup 类型)
- */
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Linq;
- using Windows.Networking.BackgroundTransfer;
- using Windows.Storage;
- using Windows.UI.Xaml;
- using Windows.UI.Xaml.Controls;
- using Windows.Web;
- using Windows.UI.Notifications;
- using Windows.Data.Xml.Dom;
- namespace Windows10.BackgroundTask
- {
- public sealed partial class TransferGroup : Page
- {
- // 用于后台任务的分组(通过组名标识后台任务)
- private BackgroundTransferGroup _group = BackgroundTransferGroup.CreateGroup("my_group");
- // 下载任务的集合
- private ObservableCollection<TransferModel> _transfers = new ObservableCollection<TransferModel>();
- // 所有下载任务的关联的 CancellationTokenSource 对象
- private CancellationTokenSource _cancelToken = new CancellationTokenSource();
- public TransferGroup()
- {
- this.InitializeComponent();
- Init();
- }
- private async void Init()
- {
- // 指定组内任务并行执行
- _group.TransferBehavior = BackgroundTransferBehavior.Parallel;
- listView.ItemsSource = _transfers;
- // 加载指定组的下载任务
- await LoadDownloadAsync();
- }
- // 加载指定组的下载任务
- private async Task LoadDownloadAsync()
- {
- IReadOnlyList<DownloadOperation> downloads = null;
- try
- {
- // 获取指定组的下载任务
- downloads = await BackgroundDownloader.GetCurrentDownloadsForTransferGroupAsync(_group);
- }
- catch (Exception ex)
- {
- WriteLine(ex.ToString());
- return;
- }
- if (downloads.Count > )
- {
- List<Task> tasks = new List<Task>();
- foreach (DownloadOperation download in downloads)
- {
- // 监视指定的后台下载任务
- tasks.Add(HandleDownloadAsync(download, false));
- }
- await Task.WhenAll(tasks);
- }
- }
- // 新增一组(3 个)下载任务
- private async void btnAddDownload_Click(object sender, RoutedEventArgs e)
- {
- BackgroundDownloader backgroundDownloader = new BackgroundDownloader();
- // 指定分组
- backgroundDownloader.TransferGroup = _group;
- // 组任务全部成功后弹出指定的 toast 通知(类似的还有 SuccessTileNotification, FailureToastNotification, FailureTileNotification)
- backgroundDownloader.SuccessToastNotification = GetToastNotification(_group.Name);
- List<DownloadOperation> downloads = new List<DownloadOperation>();
- for (int i = ; i < ; i++)
- {
- Uri sourceUri = new Uri("http://files.cnblogs.com/webabcd/Windows10.rar", UriKind.Absolute);
- StorageFile destinationFile;
- try
- {
- // 保存的目标地址(别忘了在 Package.appxmanifest 中配置好 <Capability Name="documentsLibrary" /> 和 .rar 类型文件的关联)
- StorageFolder storageFolder = await KnownFolders.GetFolderForUserAsync(null, KnownFolderId.DocumentsLibrary);
- destinationFile = await storageFolder.CreateFileAsync("Windows10.rar", CreationCollisionOption.GenerateUniqueName);
- }
- catch (Exception ex)
- {
- WriteLine(ex.ToString());
- return;
- }
- // 创建一个后台下载任务
- DownloadOperation download = backgroundDownloader.CreateDownload(sourceUri, destinationFile);
- downloads.Add(download);
- }
- // 处理并监视组内的后台下载任务
- Task[] tasks = new Task[downloads.Count];
- for (int i = ; i < downloads.Count; i++)
- {
- tasks[i] = HandleDownloadAsync(downloads[i], true);
- }
- await Task.WhenAll(tasks);
- }
- /// <summary>
- /// 处理并监视组内的后台下载任务
- /// </summary>
- /// <param name="download">后台下载任务</param>
- /// <param name="isNew">是否是新增的任务</param>
- private async Task HandleDownloadAsync(DownloadOperation download, bool isNew)
- {
- try
- {
- // 构造显示用的相关数据
- TransferModel transfer = new TransferModel();
- transfer.DownloadOperation = download;
- transfer.Source = download.RequestedUri.ToString();
- transfer.Destination = download.ResultFile.Path;
- transfer.Progress = download.Progress.Status.ToString() + ": 0 / 0";
- _transfers.Add(transfer);
- WriteLine("Task Count: " + _transfers.Count.ToString());
- // 当下载进度发生变化时的回调函数
- Progress<DownloadOperation> progressCallback = new Progress<DownloadOperation>(DownloadProgress);
- if (isNew)
- await download.StartAsync().AsTask(_cancelToken.Token, progressCallback); // 启动一个后台下载任务
- else
- await download.AttachAsync().AsTask(_cancelToken.Token, progressCallback); // 监视已存在的后台下载任务
- // 下载完成后获取服务端的响应信息
- ResponseInformation response = download.GetResponseInformation();
- WriteLine("Completed: " + response.ActualUri + ", HttpStatusCode: " + response.StatusCode.ToString());
- }
- catch (TaskCanceledException) // 调用 CancellationTokenSource.Cancel() 后会抛出此异常
- {
- WriteLine("Canceled: " + download.Guid);
- }
- catch (Exception ex)
- {
- // 将异常转换为 WebErrorStatus 枚举,如果获取到的是 WebErrorStatus.Unknown 则说明此次异常不是涉及 web 的异常
- WebErrorStatus error = BackgroundTransferError.GetStatus(ex.HResult);
- WriteLine(ex.ToString());
- }
- finally
- {
- _transfers.Remove(_transfers.First(p => p.DownloadOperation == download));
- }
- }
- // 进度发生变化时,更新 TransferModel 的 Progress
- private void DownloadProgress(DownloadOperation download)
- {
- TransferModel transfer = _transfers.First(p => p.DownloadOperation == download);
- transfer.Progress = download.Progress.Status.ToString() + ": " + download.Progress.BytesReceived.ToString("#,0") + " / " + download.Progress.TotalBytesToReceive.ToString("#,0");
- }
- // 取消全部后台下载任务
- private void btnCancel_Click(object sender, RoutedEventArgs e)
- {
- _cancelToken.Cancel();
- _cancelToken.Dispose();
- _cancelToken = new CancellationTokenSource();
- }
- // 向 lblMsg 中追加一行文本
- private void WriteLine(string message)
- {
- lblMsg.Text += message;
- lblMsg.Text += Environment.NewLine;
- scrollViewer.ChangeView(, scrollViewer.ScrollableHeight, 1f);
- }
- private ToastNotification GetToastNotification(string groupName)
- {
- string toastXml = $@"
- <toast activationType='foreground'>
- <visual>
- <binding template='ToastGeneric'>
- <text>toast - title</text>
- <text>组 {groupName} 中的下载任务全部完成了</text>
- </binding>
- </visual>
- </toast>";
- XmlDocument toastDoc = new XmlDocument();
- toastDoc.LoadXml(toastXml);
- return new ToastNotification(toastDoc);
- }
- }
- }
OK
[源码下载]
背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知)的更多相关文章
- 背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务)
[源码下载] 背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务) 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台下 ...
- 背水一战 Windows 10 (117) - 后台任务: 后台下载任务
[源码下载] 背水一战 Windows 10 (117) - 后台任务: 后台下载任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台下载任务 示例演示 uwp 的后台下 ...
- 背水一战 Windows 10 (120) - 后台任务: 后台上传任务
[源码下载] 背水一战 Windows 10 (120) - 后台任务: 后台上传任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台上传任务 示例演示 uwp 的后台上 ...
- 背水一战 Windows 10 (121) - 后台任务: 推送通知
[源码下载] 背水一战 Windows 10 (121) - 后台任务: 推送通知 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 推送通知 示例演示如何接收推送通知/WebA ...
- 背水一战 Windows 10 (115) - 后台任务: 通过 toast 激活后台任务, 定时激活后台任务
[源码下载] 背水一战 Windows 10 (115) - 后台任务: 通过 toast 激活后台任务, 定时激活后台任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 通 ...
- 背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务
[源码下载] 背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 前台程序激活后台任务 示例演示后 ...
- 背水一战 Windows 10 (114) - 后台任务: 后台任务的 Demo(与 app 不同进程), 后台任务的 Demo(与 app 相同进程)
[源码下载] 背水一战 Windows 10 (114) - 后台任务: 后台任务的 Demo(与 app 不同进程), 后台任务的 Demo(与 app 相同进程) 作者:webabcd 介绍背水一 ...
- 背水一战 Windows 10 (67) - 控件(控件基类): DependencyObject - CoreDispatcher, 依赖属性的设置与获取, 依赖属性的变化回调
[源码下载] 背水一战 Windows 10 (67) - 控件(控件基类): DependencyObject - CoreDispatcher, 依赖属性的设置与获取, 依赖属性的变化回调 作者: ...
- 背水一战 Windows 10 (59) - 控件(媒体类): Image, MediaElement
[源码下载] 背水一战 Windows 10 (59) - 控件(媒体类): Image, MediaElement 作者:webabcd 介绍背水一战 Windows 10 之 控件(媒体类) Im ...
随机推荐
- Python基础-python流程控制之循环结构(五)
循环结构 循环结构可以减少源程序重复书写的代码量,用来描述重复执行某段算法的问题. Python中循环结构分为两类,分别是 while 和 for .. in. 一.while循环 格式1: whil ...
- MySQL主主
MySQL双主(主主)架构方案 在企业中,数据库高可用一直是企业的重中之重,中小企业很多都是使用mysql主从方案,一主多从,读写分离等,但是单主存在单点故障,从库切换成主库需要作改动.因此,如果 ...
- ROS零门槛学渣教程系列前言
为什么选择ROS: 1.ROS是开放源码的,在该平台上可以找到非常很多免费开源的代码包,并且这些例程还带wiki说明文档: 2.机器人领域最新的算法直接支持ROS,简单几个步骤就能运行: 3.ROS工 ...
- Cannot attach medium 'D:\program\VirtualBox\VBoxGuestAdditions.iso' {}: medium is already associated with the current state of machine uuid {}返回 代码: VBOX_E_OBJECT_IN_USE (0x80BB000C)
详细的错误信息如下: Cannot attach medium 'D:\program\VirtualBox\VBoxGuestAdditions.iso' {83b35b10-8fa2-4b81-8 ...
- pycharm 有些模块没有提示 解决方法
解决方法:右键模块所在文件夹,选择make directory as ,选择excluded或者sources root,即可.
- android studio 模拟器不能使用的解决方案
1.安装模拟器的时候 AS提示是 VT -x is disable 进入电脑的 bios 系统设置,怎么进入--> 在开机的时候点击F2(华硕电脑,不同电脑方式不同) --在“configura ...
- Springboot访问静态资源
转载 http://blog.csdn.net/catoop/article/details/50501706
- 《修炼之道:.NET开发要点精讲》读书笔记(一)
CLR 公共语言运行库 没有CLR的存在,就不能讲该中间件转换成对应操作系统中的机器指令. 程序集是非完全编译的产物,它兼备了源代码和本地代码的特性,是一种介于源代码和本地代码之间的独立存在的一种数据 ...
- PostgreSQL uuid
--执行一 create extension "uuid-ossp" --执行二 select uuid_generate_v4()
- JS格式化日期时间的方法
//格式化时间的方法 function format(fmt, date) { var o = { "M+": date.getMonth() + 1, //月份 "d+ ...