背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含13572字,纯文字阅读大概需要20分钟。
内容图文
作者:webabcd
介绍
背水一战 Windows 10 之 后台任务
- 后台下载任务(任务分组,组完成后触发后台任务)
示例
演示后台下载任务的分组,以及组任务全部完成后如何触发后台任务
/BackgroundTaskLib/BackgroundTaskTransfer.cs
/* * 后台任务,用于演示指定的一组后台下载任务全部完成后如何触发此后台任务 * * BackgroundTransferCompletionGroup - 分组对象(用于实现“组任务全部完成后触发后台任务”) * Enable() - 启用“组任务全部完成后触发后台任务”的功能 * IsEnabled - 是否启用了“组任务全部完成后触发后台任务”的功能(只读) * Trigger - “组任务全部完成后触发后台任务”的触发器 * * BackgroundDownloader - 后台下载任务管理器 * BackgroundDownloader(BackgroundTransferCompletionGroup completionGroup) - 通过指定的 BackgroundTransferCompletionGroup 对象实例化 BackgroundDownloader 对象 * CompletionGroup - 获取关联的 BackgroundTransferCompletionGroup 对象 * * * 注:需要在 Package.appxmanifest 添加“后台任务”声明,支持的任务类型选择“系统事件”,并指定 EntryPoint(后台任务的类全名),类似如下: * <Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTaskLib.BackgroundTaskTransfer"> * <BackgroundTasks> * <Task Type="systemEvent" /> * </BackgroundTasks> * </Extension> */ using System; using System.Collections.Generic; using System.Threading.Tasks; using Windows.ApplicationModel.Background; using Windows.Data.Xml.Dom; using Windows.Networking.BackgroundTransfer; using Windows.UI.Notifications; namespace BackgroundTaskLib { public sealed class BackgroundTaskTransfer : IBackgroundTask { // 所注册的后台任务的名称 public static string TaskName { get; set; } = "Transfer"; // 所注册的后台任务的 EntryPoint,即后台任务的类全名publicstaticstring TaskEntryPoint { get; set; } = "BackgroundTaskLib.BackgroundTaskTransfer"; // 实现 IBackgroundTask 接口,其只有一个方法,即 Run()publicvoid Run(IBackgroundTaskInstance taskInstance) { // 获取 BackgroundTransferCompletionGroupTriggerDetails 对象,如果不是 null 则说明是 BackgroundTransferCompletionGroup.Trigger 触发的 BackgroundTransferCompletionGroupTriggerDetails details = taskInstance.TriggerDetails as BackgroundTransferCompletionGroupTriggerDetails; if (details == null) { return; } // 获取下载任务列表 List<DownloadOperation> failedDownloads = new List<DownloadOperation>(); int successTotal = 0; foreach (DownloadOperation download in details.Downloads) { if (IsFailed(download)) { // 保存失败的下载任务列表,稍后会重试 failedDownloads.Add(download); } else { successTotal++; } } if (failedDownloads.Count > 0) { // 重新下载失败的任务 RetryDownloads(failedDownloads); } // 此后台任务执行完毕,弹出指定的 toast 通知 ShowToast(successTotal, failedDownloads.Count); } // 判断指定的下载任务是否失败了privatebool IsFailed(DownloadOperation download) { BackgroundTransferStatus status = download.Progress.Status; if (status == BackgroundTransferStatus.Error || status == BackgroundTransferStatus.Canceled) { returntrue; } ResponseInformation response = download.GetResponseInformation(); if (response.StatusCode != 200) { returntrue; } returnfalse; } // 重新下载指定的任务privatevoid RetryDownloads(IEnumerable<DownloadOperation> downloads) { // 注册指定的后台任务,并返回与此后台任务相关联的 BackgroundDownloader 对象 BackgroundDownloader downloader = BackgroundTaskTransfer.RegisterBackgroundTaskAndReturnBackgrounDownloader(); foreach (DownloadOperation download in downloads) { // 创建并启动后台任务 DownloadOperation downloadNew = downloader.CreateDownload(download.RequestedUri, download.ResultFile); Task<DownloadOperation> startTask = downloadNew.StartAsync().AsTask(); } // 启用“组任务全部完成后触发后台任务”的功能 downloader.CompletionGroup.Enable(); } // 注册指定的后台任务,并返回与此后台任务相关联的 BackgroundDownloader 对象 // 后台任务的注册一般是在前台代码中写的,但是由于本例还有一个后台任务执行完成后重新下载失败任务的功能,所以这部分代码写在后台代码中就很合理了publicstatic BackgroundDownloader RegisterBackgroundTaskAndReturnBackgrounDownloader() { // 根据指定 BackgroundTransferCompletionGroup 对象创建一个 BackgroundDownloader 对象 BackgroundTransferCompletionGroup completionGroup = new BackgroundTransferCompletionGroup(); BackgroundDownloader downloader = new BackgroundDownloader(completionGroup); // 注册一个后台任务,并指定触发器为 BackgroundTransferCompletionGroup.Trigger BackgroundTaskBuilder builder = new BackgroundTaskBuilder(); builder.Name = BackgroundTaskTransfer.TaskName; builder.TaskEntryPoint = BackgroundTaskTransfer.TaskEntryPoint; builder.SetTrigger(completionGroup.Trigger); BackgroundTaskRegistration task = builder.Register(); return downloader; } // 后台任务执行完成后弹出 toast 通知privatevoid ShowToast(int successTotal, int failureTotal) { string toastXml = $@" <toast activationType=‘foreground‘> <visual> <binding template=‘ToastGeneric‘> <text>toast - title</text> <text>下载任务成功数: {successTotal}</text> <text>下载任务失败数: {failureTotal}</text> </binding> </visual> </toast>"; XmlDocument toastDoc = new XmlDocument(); toastDoc.LoadXml(toastXml); ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toastDoc)); } } }
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; } publicstring Source { get; set; } publicstring Destination { get; set; } privatestring _progress; publicstring Progress { get { return _progress; } set { _progress = value; RaisePropertyChanged("Progress"); } } publicevent PropertyChangedEventHandler PropertyChanged; protectedvoid RaisePropertyChanged(string name) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } } }
BackgroundTask/TransferBackground.xaml
< Page x:Class ="Windows10.BackgroundTask.TransferBackground" 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 ="btnAddDownloadAndRegister" Content ="新增一组(3 个)下载任务,并注册指定的后台任务,当这一组下载任务全部完成后触发一个后台任务。" Margin ="5" Click ="btnAddDownloadAndRegister_Click" /> < Button Name ="btnRemoveDownloadAndUnregister" Content ="取消下载任务并注销指定的后台任务" Margin ="5" Click ="btnRemoveDownloadAndUnregister_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/TransferBackground.xaml.cs
/* * 演示后台下载任务的分组,以及组任务全部完成后如何触发后台任务 * * BackgroundTransferCompletionGroup - 分组对象(用于实现“组任务全部完成后触发后台任务”) * Enable() - 启用“组任务全部完成后触发后台任务”的功能 * IsEnabled - 是否启用了“组任务全部完成后触发后台任务”的功能(只读) * Trigger - “组任务全部完成后触发后台任务”的触发器 * * BackgroundDownloader - 后台下载任务管理器 * BackgroundDownloader(BackgroundTransferCompletionGroup completionGroup) - 通过指定的 BackgroundTransferCompletionGroup 对象实例化 BackgroundDownloader 对象 * CompletionGroup - 获取关联的 BackgroundTransferCompletionGroup 对象 * * * 注:需要引用后台任务项目,相关代码参见 BackgroundTaskLib/BackgroundTaskTransfer.cs */ using BackgroundTaskLib; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading; using System.Threading.Tasks; using Windows.ApplicationModel.Background; using Windows.Networking.BackgroundTransfer; using Windows.Storage; using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; using Windows.Web; namespace Windows10.BackgroundTask { public sealed partial class TransferBackground : Page { // 后台任务是否已在系统中注册 private bool _taskRegistered = false; // 下载任务的集合private ObservableCollection<TransferModel> _transfers = new ObservableCollection<TransferModel>(); // 所有下载任务的关联的 CancellationTokenSource 对象private CancellationTokenSource _cancelToken = new CancellationTokenSource(); public TransferBackground() { this.InitializeComponent(); Init(); } privateasyncvoid Init() { listView.ItemsSource = _transfers; // 加载存在的下载任务await LoadDownloadAsync(); } // 加载存在的下载任务privateasync Task LoadDownloadAsync() { IReadOnlyList<DownloadOperation> downloads = null; try { // 获取存在的下载任务 downloads = await BackgroundDownloader.GetCurrentDownloadsAsync(); } catch (Exception ex) { WriteLine(ex.ToString()); return; } if (downloads.Count > 0) { List<Task> tasks = new List<Task>(); foreach (DownloadOperation download in downloads) { // 监视指定的后台下载任务 tasks.Add(HandleDownloadAsync(download, false)); } await Task.WhenAll(tasks); } } protectedoverridevoid OnNavigatedTo(NavigationEventArgs e) { // 遍历所有已注册的后台任务foreach (KeyValuePair<Guid, IBackgroundTaskRegistration> task in BackgroundTaskRegistration.AllTasks) { if (task.Value.Name == BackgroundTaskTransfer.TaskName) { _taskRegistered = true; break; } } UpdateUI(); } // 新增一组(3 个)下载任务,并注册指定的后台任务privateasyncvoid btnAddDownloadAndRegister_Click(object sender, RoutedEventArgs e) { // 注册指定的后台任务,并返回与此后台任务相关联的 BackgroundDownloader 对象 BackgroundDownloader downloader = BackgroundTaskTransfer.RegisterBackgroundTaskAndReturnBackgrounDownloader(); _taskRegistered = true; UpdateUI(); List<DownloadOperation> downloads = new List<DownloadOperation>(); for (int i = 0; i < 3; i++) { Uri uri = new Uri("http://files.cnblogs.com/webabcd/Windows10.rar"); 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 = downloader.CreateDownload(uri, destinationFile); downloads.Add(download); } // 启用“组任务全部完成后触发后台任务”的功能 downloader.CompletionGroup.Enable(); WriteLine("用于完成后触发后台任务的一组下载任务创建完成了,相关的后台任务也注册了"); // 处理并监视组内的后台下载任务 Task[] tasks = new Task[downloads.Count]; for (int i = 0; i < downloads.Count; i++) { tasks[i] = HandleDownloadAsync(downloads[i], true); } await Task.WhenAll(tasks); } ///<summary>/// 处理并监视组内的后台下载任务 ///</summary>///<param name="download">后台下载任务</param>///<param name="isNew">是否是新增的任务</param>privateasync 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); // 启动一个后台下载任务elseawait 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 的 Progressprivatevoid 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"); } // 向 lblMsg 中追加一行文本privatevoid WriteLine(string message) { var ignore = lblMsg.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { lblMsg.Text += message; lblMsg.Text += Environment.NewLine; scrollViewer.ChangeView(0, scrollViewer.ScrollableHeight, 1f); }); } // 取消下载任务并注销指定的后台任务privatevoid btnRemoveDownloadAndUnregister_Click(object sender, RoutedEventArgs e) { // 取消下载任务 _cancelToken.Cancel(); _cancelToken.Dispose(); _cancelToken = new CancellationTokenSource(); // 注销指定的后台任务foreach (KeyValuePair<Guid, IBackgroundTaskRegistration> task in BackgroundTaskRegistration.AllTasks) { if (task.Value.Name == BackgroundTaskTransfer.TaskName) { // 从系统中注销指定的后台任务。唯一一个参数代表如果当前后台任务正在运行中,是否需要将其取消 task.Value.Unregister(true); break; } } _taskRegistered = false; UpdateUI(); } privateasyncvoid UpdateUI() { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { btnAddDownloadAndRegister.IsEnabled = !_taskRegistered; btnRemoveDownloadAndUnregister.IsEnabled = _taskRegistered; }); } } }
OK
[源码下载]
原文:https://www.cnblogs.com/webabcd/p/9211759.html
内容总结
以上是互联网集市为您收集整理的背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务)全部内容,希望文章能够帮你解决背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。