[源码下载]

背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知)

作者:webabcd

介绍
背水一战 Windows 10 之 后台任务

  • 后台下载任务(任务分组,并行或串行执行,组完成后通知)

示例
演示后台下载任务的分组,以及如何设置组内任务是并行执行还是串行执行,以及组任务全部完成后如何 toast 或 tile 通知)
BackgroundTask/TransferModel.cs

  1. /*
  2. * 扩展了 DownloadOperation 和 UploadOperation,用于 MVVM 绑定数据
  3. */
  4.  
  5. using System;
  6. using System.ComponentModel;
  7. using Windows.Networking.BackgroundTransfer;
  8.  
  9. namespace Windows10.BackgroundTask
  10. {
  11. public class TransferModel : INotifyPropertyChanged
  12. {
  13. public DownloadOperation DownloadOperation { get; set; }
  14. public UploadOperation UploadOperation { get; set; }
  15.  
  16. public string Source { get; set; }
  17. public string Destination { get; set; }
  18.  
  19. private string _progress;
  20. public string Progress
  21. {
  22. get { return _progress; }
  23. set
  24. {
  25. _progress = value;
  26. RaisePropertyChanged("Progress");
  27. }
  28. }
  29.  
  30. public event PropertyChangedEventHandler PropertyChanged;
  31. protected void RaisePropertyChanged(string name)
  32. {
  33. if (PropertyChanged != null)
  34. {
  35. PropertyChanged(this, new PropertyChangedEventArgs(name));
  36. }
  37. }
  38. }
  39. }

BackgroundTask/TransferGroup.xaml

  1. <Page
  2. x:Class="Windows10.BackgroundTask.TransferGroup"
  3. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5. xmlns:local="using:Windows10.BackgroundTask"
  6. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  7. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  8. mc:Ignorable="d">
  9.  
  10. <Grid Background="Transparent">
  11. <StackPanel Margin="10 0 10 10">
  12.  
  13. <ScrollViewer Name="scrollViewer" Height="100" Margin="5">
  14. <TextBlock Name="lblMsg" TextWrapping="Wrap" />
  15. </ScrollViewer>
  16.  
  17. <Button Name="btnAddDownload" Content="新增一组(3 个)下载任务,可以指定其是并发还是串行,当这一组的所有任务都完成后弹出通知" Margin="5" Click="btnAddDownload_Click" />
  18. <Button Name="btnCancel" Content="取消所有下载任务" Margin="5" Click="btnCancel_Click" />
  19.  
  20. <ListView Name="listView" Height="286" Padding="5">
  21. <ListView.ItemTemplate>
  22. <DataTemplate>
  23. <StackPanel Margin="0 5" Background="Blue">
  24. <TextBlock Text="{Binding Source}" Margin="5" />
  25. <TextBlock Text="{Binding Destination}" Margin="5" />
  26. <TextBlock Text="{Binding Progress}" Margin="5" />
  27. </StackPanel>
  28. </DataTemplate>
  29. </ListView.ItemTemplate>
  30. </ListView>
  31.  
  32. </StackPanel>
  33. </Grid>
  34. </Page>

BackgroundTask/TransferGroup.xaml.cs

  1. /*
  2. * 演示后台下载任务的分组,以及如何设置组内任务是并行执行还是串行执行,以及组任务全部完成后如何 toast 或 tile 通知)
  3. *
  4. * BackgroundTransferGroup - 后台下载任务的分组对象
  5. * static BackgroundTransferGroup CreateGroup(string name) - 创建指定分组标识的 BackgroundTransferGroup 对象
  6. * Name - 分组标识(只读)
  7. * TransferBehavior - 组内下载任务的执行方式,BackgroundTransferBehavior 枚举
  8. * Parallel - 并行
  9. * Serialized - 串行
  10. *
  11. * BackgroundDownloader - 后台下载任务管理器
  12. * TransferGroup - 设置或获取分组对象(BackgroundTransferGroup 类型)
  13. * static GetCurrentDownloadsForTransferGroupAsync(BackgroundTransferGroup group) - 获取指定组的所有下载任务
  14. *
  15. * DownloadOperation - 下载任务对象
  16. * TransferGroup - 获取此下载任务的分组对象(BackgroundTransferGroup 类型)
  17. */
  18.  
  19. using System;
  20. using System.Collections.Generic;
  21. using System.Collections.ObjectModel;
  22. using System.Threading;
  23. using System.Threading.Tasks;
  24. using System.Linq;
  25. using Windows.Networking.BackgroundTransfer;
  26. using Windows.Storage;
  27. using Windows.UI.Xaml;
  28. using Windows.UI.Xaml.Controls;
  29. using Windows.Web;
  30. using Windows.UI.Notifications;
  31. using Windows.Data.Xml.Dom;
  32.  
  33. namespace Windows10.BackgroundTask
  34. {
  35. public sealed partial class TransferGroup : Page
  36. {
  37. // 用于后台任务的分组(通过组名标识后台任务)
  38. private BackgroundTransferGroup _group = BackgroundTransferGroup.CreateGroup("my_group");
  39.  
  40. // 下载任务的集合
  41. private ObservableCollection<TransferModel> _transfers = new ObservableCollection<TransferModel>();
  42.  
  43. // 所有下载任务的关联的 CancellationTokenSource 对象
  44. private CancellationTokenSource _cancelToken = new CancellationTokenSource();
  45.  
  46. public TransferGroup()
  47. {
  48. this.InitializeComponent();
  49.  
  50. Init();
  51. }
  52.  
  53. private async void Init()
  54. {
  55. // 指定组内任务并行执行
  56. _group.TransferBehavior = BackgroundTransferBehavior.Parallel;
  57.  
  58. listView.ItemsSource = _transfers;
  59.  
  60. // 加载指定组的下载任务
  61. await LoadDownloadAsync();
  62. }
  63.  
  64. // 加载指定组的下载任务
  65. private async Task LoadDownloadAsync()
  66. {
  67. IReadOnlyList<DownloadOperation> downloads = null;
  68. try
  69. {
  70. // 获取指定组的下载任务
  71. downloads = await BackgroundDownloader.GetCurrentDownloadsForTransferGroupAsync(_group);
  72. }
  73. catch (Exception ex)
  74. {
  75. WriteLine(ex.ToString());
  76. return;
  77. }
  78.  
  79. if (downloads.Count > )
  80. {
  81. List<Task> tasks = new List<Task>();
  82. foreach (DownloadOperation download in downloads)
  83. {
  84. // 监视指定的后台下载任务
  85. tasks.Add(HandleDownloadAsync(download, false));
  86. }
  87.  
  88. await Task.WhenAll(tasks);
  89. }
  90. }
  91.  
  92. // 新增一组(3 个)下载任务
  93. private async void btnAddDownload_Click(object sender, RoutedEventArgs e)
  94. {
  95. BackgroundDownloader backgroundDownloader = new BackgroundDownloader();
  96. // 指定分组
  97. backgroundDownloader.TransferGroup = _group;
  98. // 组任务全部成功后弹出指定的 toast 通知(类似的还有 SuccessTileNotification, FailureToastNotification, FailureTileNotification)
  99. backgroundDownloader.SuccessToastNotification = GetToastNotification(_group.Name);
  100.  
  101. List<DownloadOperation> downloads = new List<DownloadOperation>();
  102. for (int i = ; i < ; i++)
  103. {
  104. Uri sourceUri = new Uri("http://files.cnblogs.com/webabcd/Windows10.rar", UriKind.Absolute);
  105.  
  106. StorageFile destinationFile;
  107. try
  108. {
  109. // 保存的目标地址(别忘了在 Package.appxmanifest 中配置好 <Capability Name="documentsLibrary" /> 和 .rar 类型文件的关联)
  110. StorageFolder storageFolder = await KnownFolders.GetFolderForUserAsync(null, KnownFolderId.DocumentsLibrary);
  111. destinationFile = await storageFolder.CreateFileAsync("Windows10.rar", CreationCollisionOption.GenerateUniqueName);
  112. }
  113. catch (Exception ex)
  114. {
  115. WriteLine(ex.ToString());
  116. return;
  117. }
  118. // 创建一个后台下载任务
  119. DownloadOperation download = backgroundDownloader.CreateDownload(sourceUri, destinationFile);
  120.  
  121. downloads.Add(download);
  122. }
  123.  
  124. // 处理并监视组内的后台下载任务
  125. Task[] tasks = new Task[downloads.Count];
  126. for (int i = ; i < downloads.Count; i++)
  127. {
  128. tasks[i] = HandleDownloadAsync(downloads[i], true);
  129. }
  130.  
  131. await Task.WhenAll(tasks);
  132.  
  133. }
  134.  
  135. /// <summary>
  136. /// 处理并监视组内的后台下载任务
  137. /// </summary>
  138. /// <param name="download">后台下载任务</param>
  139. /// <param name="isNew">是否是新增的任务</param>
  140. private async Task HandleDownloadAsync(DownloadOperation download, bool isNew)
  141. {
  142. try
  143. {
  144. // 构造显示用的相关数据
  145. TransferModel transfer = new TransferModel();
  146. transfer.DownloadOperation = download;
  147. transfer.Source = download.RequestedUri.ToString();
  148. transfer.Destination = download.ResultFile.Path;
  149. transfer.Progress = download.Progress.Status.ToString() + ": 0 / 0";
  150.  
  151. _transfers.Add(transfer);
  152.  
  153. WriteLine("Task Count: " + _transfers.Count.ToString());
  154.  
  155. // 当下载进度发生变化时的回调函数
  156. Progress<DownloadOperation> progressCallback = new Progress<DownloadOperation>(DownloadProgress);
  157.  
  158. if (isNew)
  159. await download.StartAsync().AsTask(_cancelToken.Token, progressCallback); // 启动一个后台下载任务
  160. else
  161. await download.AttachAsync().AsTask(_cancelToken.Token, progressCallback); // 监视已存在的后台下载任务
  162.  
  163. // 下载完成后获取服务端的响应信息
  164. ResponseInformation response = download.GetResponseInformation();
  165. WriteLine("Completed: " + response.ActualUri + ", HttpStatusCode: " + response.StatusCode.ToString());
  166. }
  167. catch (TaskCanceledException) // 调用 CancellationTokenSource.Cancel() 后会抛出此异常
  168. {
  169. WriteLine("Canceled: " + download.Guid);
  170. }
  171. catch (Exception ex)
  172. {
  173. // 将异常转换为 WebErrorStatus 枚举,如果获取到的是 WebErrorStatus.Unknown 则说明此次异常不是涉及 web 的异常
  174. WebErrorStatus error = BackgroundTransferError.GetStatus(ex.HResult);
  175.  
  176. WriteLine(ex.ToString());
  177. }
  178. finally
  179. {
  180. _transfers.Remove(_transfers.First(p => p.DownloadOperation == download));
  181. }
  182. }
  183.  
  184. // 进度发生变化时,更新 TransferModel 的 Progress
  185. private void DownloadProgress(DownloadOperation download)
  186. {
  187. TransferModel transfer = _transfers.First(p => p.DownloadOperation == download);
  188. transfer.Progress = download.Progress.Status.ToString() + ": " + download.Progress.BytesReceived.ToString("#,0") + " / " + download.Progress.TotalBytesToReceive.ToString("#,0");
  189. }
  190.  
  191. // 取消全部后台下载任务
  192. private void btnCancel_Click(object sender, RoutedEventArgs e)
  193. {
  194. _cancelToken.Cancel();
  195. _cancelToken.Dispose();
  196.  
  197. _cancelToken = new CancellationTokenSource();
  198. }
  199.  
  200. // 向 lblMsg 中追加一行文本
  201. private void WriteLine(string message)
  202. {
  203. lblMsg.Text += message;
  204. lblMsg.Text += Environment.NewLine;
  205.  
  206. scrollViewer.ChangeView(, scrollViewer.ScrollableHeight, 1f);
  207. }
  208.  
  209. private ToastNotification GetToastNotification(string groupName)
  210. {
  211. string toastXml = $@"
  212. <toast activationType='foreground'>
  213. <visual>
  214. <binding template='ToastGeneric'>
  215. <text>toast - title</text>
  216. <text>组 {groupName} 中的下载任务全部完成了</text>
  217. </binding>
  218. </visual>
  219. </toast>";
  220.  
  221. XmlDocument toastDoc = new XmlDocument();
  222. toastDoc.LoadXml(toastXml);
  223.  
  224. return new ToastNotification(toastDoc);
  225. }
  226. }
  227. }

OK
[源码下载]

背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知)的更多相关文章

  1. 背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务)

    [源码下载] 背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务) 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台下 ...

  2. 背水一战 Windows 10 (117) - 后台任务: 后台下载任务

    [源码下载] 背水一战 Windows 10 (117) - 后台任务: 后台下载任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台下载任务 示例演示 uwp 的后台下 ...

  3. 背水一战 Windows 10 (120) - 后台任务: 后台上传任务

    [源码下载] 背水一战 Windows 10 (120) - 后台任务: 后台上传任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台上传任务 示例演示 uwp 的后台上 ...

  4. 背水一战 Windows 10 (121) - 后台任务: 推送通知

    [源码下载] 背水一战 Windows 10 (121) - 后台任务: 推送通知 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 推送通知 示例演示如何接收推送通知/WebA ...

  5. 背水一战 Windows 10 (115) - 后台任务: 通过 toast 激活后台任务, 定时激活后台任务

    [源码下载] 背水一战 Windows 10 (115) - 后台任务: 通过 toast 激活后台任务, 定时激活后台任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 通 ...

  6. 背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务

    [源码下载] 背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 前台程序激活后台任务 示例演示后 ...

  7. 背水一战 Windows 10 (114) - 后台任务: 后台任务的 Demo(与 app 不同进程), 后台任务的 Demo(与 app 相同进程)

    [源码下载] 背水一战 Windows 10 (114) - 后台任务: 后台任务的 Demo(与 app 不同进程), 后台任务的 Demo(与 app 相同进程) 作者:webabcd 介绍背水一 ...

  8. 背水一战 Windows 10 (67) - 控件(控件基类): DependencyObject - CoreDispatcher, 依赖属性的设置与获取, 依赖属性的变化回调

    [源码下载] 背水一战 Windows 10 (67) - 控件(控件基类): DependencyObject - CoreDispatcher, 依赖属性的设置与获取, 依赖属性的变化回调 作者: ...

  9. 背水一战 Windows 10 (59) - 控件(媒体类): Image, MediaElement

    [源码下载] 背水一战 Windows 10 (59) - 控件(媒体类): Image, MediaElement 作者:webabcd 介绍背水一战 Windows 10 之 控件(媒体类) Im ...

随机推荐

  1. Python基础-python流程控制之循环结构(五)

    循环结构 循环结构可以减少源程序重复书写的代码量,用来描述重复执行某段算法的问题. Python中循环结构分为两类,分别是 while 和 for .. in. 一.while循环 格式1: whil ...

  2. MySQL主主

    MySQL双主(主主)架构方案   在企业中,数据库高可用一直是企业的重中之重,中小企业很多都是使用mysql主从方案,一主多从,读写分离等,但是单主存在单点故障,从库切换成主库需要作改动.因此,如果 ...

  3. ROS零门槛学渣教程系列前言

    为什么选择ROS: 1.ROS是开放源码的,在该平台上可以找到非常很多免费开源的代码包,并且这些例程还带wiki说明文档: 2.机器人领域最新的算法直接支持ROS,简单几个步骤就能运行: 3.ROS工 ...

  4. 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 ...

  5. pycharm 有些模块没有提示 解决方法

    解决方法:右键模块所在文件夹,选择make directory as ,选择excluded或者sources root,即可.

  6. android studio 模拟器不能使用的解决方案

    1.安装模拟器的时候 AS提示是 VT -x is disable 进入电脑的 bios 系统设置,怎么进入--> 在开机的时候点击F2(华硕电脑,不同电脑方式不同) --在“configura ...

  7. Springboot访问静态资源

    转载 http://blog.csdn.net/catoop/article/details/50501706

  8. 《修炼之道:.NET开发要点精讲》读书笔记(一)

    CLR 公共语言运行库 没有CLR的存在,就不能讲该中间件转换成对应操作系统中的机器指令. 程序集是非完全编译的产物,它兼备了源代码和本地代码的特性,是一种介于源代码和本地代码之间的独立存在的一种数据 ...

  9. PostgreSQL uuid

    --执行一 create extension "uuid-ossp" --执行二 select uuid_generate_v4()

  10. JS格式化日期时间的方法

    //格式化时间的方法 function format(fmt, date) { var o = { "M+": date.getMonth() + 1, //月份 "d+ ...