zoukankan      html  css  js  c++  java
  • 背水一战 Windows 10 (118)

    [源码下载]


    背水一战 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 > 0)
                {
                    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 = 0; i < 3; 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 = 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>
            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(0, 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
    [源码下载]

  • 相关阅读:
    December 23rd 2016 Week 52nd Friday
    December 22nd 2016 Week 52nd Thursday
    December 21st 2016 Week 52nd Wednesday
    December 20th 2016 Week 52nd Tuesday
    December 19th 2016 Week 52nd Sunday
    December 18th 2016 Week 52nd Sunday
    uva294(唯一分解定理)
    uva11624Fire!(bfs)
    fzu2150Fire Game(双起点bfs)
    poj3276Face The Right Way
  • 原文地址:https://www.cnblogs.com/webabcd/p/9211752.html
Copyright © 2011-2022 走看看