新时尚Windows8开发(35):后台传输,新时尚windows8
新时尚Windows8开发(35):后台传输,新时尚windows8
所谓后台传输,关键是突出在,在应用程序不在前台运行时,它仍然可以进行数据传输,一般而言,这个功能用于下载文件比较适合,像“应用商店”的下载应用就是使用了后台传输。
这个后台传输当然包括下载和上传了,不过,我想是下载的情况会多一些,呵呵,不知道是不是这样,元芳,你怎么看?
好了,不管元芳怎么看了,首先大家做好心理准备,接下来我会讲一点点比较枯燥的东东,不怕,只是一点点而已,我不喜欢长篇巨论,免得各位看着看着就睡觉了。
实现后台下载,一般有以下几步要走:
引入Windows.Networking.BackgroundTransfer命名空间。
new一个BackgroundDownloader(如果下载数据)或者一个BackgroundUploader(如果是下载)。
如果是BackgroundDownloader,就调用CreateDownload方法创建DownloadOperation实例,如果是BackgroundUploader,就调用CreateUpload方法创建UploadOperation实例;
此时调用DownloadOperation的StartAsync方法或者UploadOperation的StartAsync方法开始干活。
这里因为涉及到操作进度,所以要使用WindowsRuntimeSystemExtensions类为Windows.Foundation.IAsyncOperationWithProgress<TResult, TProgress>所定义的扩展方法AsTask,这个我不深入讲了,看看例子就知道,呵呵,那可是C# 5.0的妙用!!
OK,枯燥期已过,下面是激情期,这个例子不复杂,就是输入一个MP3的下载地址,然后下载。
【XAML】
[html]
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="27"/>
<Setter Property="FontFamily" Value="宋体"/>
</Style>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="15,8" Orientation="Horizontal">
<TextBlock Text="输入下载URI:" VerticalAlignment="Center" />
<TextBox x:Name="txtInputUri" Width="680"/>
<Button x:Name="btnDown" Margin="38,0,0,0" VerticalAlignment="Center" Content="开始下载" Padding="17,5,17,5" FontSize="22" Click="onDownload_Click"/>
</StackPanel>
<StackPanel Grid.Row="1" Margin="20">
<ProgressBar x:Name="probar" Maximum="100" Minimum="0" SmallChange="1" Width="700" HorizontalAlignment="Left" Foreground="Yellow"
Height="30" Margin="6,21,0,35"/>
<TextBlock x:Name="tbMsg" Margin="6,8,0,0" />
</StackPanel>
</Grid>
</Page>
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="27"/>
<Setter Property="FontFamily" Value="宋体"/>
</Style>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="15,8" Orientation="Horizontal">
<TextBlock Text="输入下载URI:" VerticalAlignment="Center" />
<TextBox x:Name="txtInputUri" Width="680"/>
<Button x:Name="btnDown" Margin="38,0,0,0" VerticalAlignment="Center" Content="开始下载" Padding="17,5,17,5" FontSize="22" Click="onDownload_Click"/>
</StackPanel>
<StackPanel Grid.Row="1" Margin="20">
<ProgressBar x:Name="probar" Maximum="100" Minimum="0" SmallChange="1" Width="700" HorizontalAlignment="Left" Foreground="Yellow"
Height="30" Margin="6,21,0,35"/>
<TextBlock x:Name="tbMsg" Margin="6,8,0,0" />
</StackPanel>
</Grid>
</Page>
其中,ProgressBar当然是用来显示进度了,其它控件,估计各位是N + 6的熟悉了。
【C#】
[csharp]
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
//
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
namespace App1
{
/// <summary>
/// 可用于自身或导航至 Frame 内部的空白页。
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void onDownload_Click(object sender, RoutedEventArgs e)
{
// 判断是否已输入下载URI
if (string.IsNullOrWhiteSpace(this.txtInputUri.Text)) return;
// 选择文件保存位置
FileSavePicker picker = new FileSavePicker();
picker.FileTypeChoices.Add("MP3文件", new string[] { ".mp3" });
StorageFile file = await picker.PickSaveFileAsync();
if (file != null)
{
// 实例化BackgroundDownloader
BackgroundDownloader downloader = new BackgroundDownloader();
DownloadOperation operation = downloader.CreateDownload(new Uri(this.txtInputUri.Text), file);
// 进度
Progress<DownloadOperation> progressDown = new Progress<DownloadOperation>(this.ProgressChanged);
// 开始下载
btnDown.IsEnabled = false;
var opresult = await operation.StartAsync().AsTask(progressDown);
btnDown.IsEnabled = true;
// 判断下载结果
switch (opresult.Progress.Status)
{
case BackgroundTransferStatus.Completed:
tbMsg.Text = "下载已完成。";
break;
case BackgroundTransferStatus.Error:
tbMsg.Text = "下载过程中发生了错误。";
break;
default:
tbMsg.Text = "未知。";
break;
}
}
}
/// <summary>
/// 报告进度
/// </summary>
private async void ProgressChanged(DownloadOperation op)
{
var p = op.Progress;
double t = p.TotalBytesToReceive;//要下载总字节数
double d = p.BytesReceived;//已接收字节数
// 计算完成百分比
double pc = d / t * 100;
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
this.probar.Value = pc;
this.tbMsg.Text = string.Format("已下载{0}字节/共{1}字节。", d.ToString("N0"), t.ToString("N0"));
});
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
//
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
namespace App1
{
/// <summary>
/// 可用于自身或导航至 Frame 内部的空白页。
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void onDownload_Click(object sender, RoutedEventArgs e)
{
// 判断是否已输入下载URI
if (string.IsNullOrWhiteSpace(this.txtInputUri.Text)) return;
// 选择文件保存位置
FileSavePicker picker = new FileSavePicker();
picker.FileTypeChoices.Add("MP3文件", new string[] { ".mp3" });
StorageFile file = await picker.PickSaveFileAsync();
if (file != null)
{
// 实例化BackgroundDownloader
BackgroundDownloader downloader = new BackgroundDownloader();
DownloadOperation operation = downloader.CreateDownload(new Uri(this.txtInputUri.Text), file);
// 进度
Progress<DownloadOperation> progressDown = new Progress<DownloadOperation>(this.ProgressChanged);
// 开始下载
btnDown.IsEnabled = false;
var opresult = await operation.StartAsync().AsTask(progressDown);
btnDown.IsEnabled = true;
// 判断下载结果
switch (opresult.Progress.Status)
{
case BackgroundTransferStatus.Completed:
tbMsg.Text = "下载已完成。";
break;
case BackgroundTransferStatus.Error:
tbMsg.Text = "下载过程中发生了错误。";
break;
default:
tbMsg.Text = "未知。";
break;
}
}
}
/// <summary>
/// 报告进度
/// </summary>
private async void ProgressChanged(DownloadOperation op)
{
var p = op.Progress;
double t = p.TotalBytesToReceive;//要下载总字节数
double d = p.BytesReceived;//已接收字节数
// 计算完成百分比
double pc = d / t * 100;
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
this.probar.Value = pc;
this.tbMsg.Text = string.Format("已下载{0}字节/共{1}字节。", d.ToString("N0"), t.ToString("N0"));
});
}
}
}
你可能会问,干吗要用Progress<T>类?
你想啊,StartAsync方法异步调用返回DownloadOperation对象,可是,你猜猜它是啥时候才能返回?还不是要等到整个文件下载完了它才返回,那么一来,你还报告个鸟进度,是不是这样呢?
而使用Progress<T>,可以传一个委托给ProgressChanged事件,说白了,就是处理这个事件,这样一来才能实时报告进度,元芳,是不是这样呢?
程序弄好之后,就是运行测试,随便找个MP3的下载地址帖上去,然后点击“开始下载”,看有没有效果?如果无误,你会看到如下图所示的内容。
用户评论