新时尚Windows8开发(35):后台传输
所谓后台传输,关键是突出在,在应用程序不在前台运行时,它仍然可以进行数据传输,一般而言,这个功能用于下载文件比较适合,像“应用商店”的下载应用就是使用了后台传输。
这个后台传输当然包括下载和上传了,不过,我想是下载的情况会多一些,呵呵,不知道是不是这样,元芳,你怎么看?
好了,不管元芳怎么看了,首先大家做好心理准备,接下来我会讲一点点比较枯燥的东东,不怕,只是一点点而已,我不喜欢长篇巨论,免得各位看着看着就睡觉了。
实现后台下载,一般有以下几步要走:
引入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的下载地址帖上去,然后点击“开始下载”,看有没有效果?如果无误,你会看到如下图所示的内容。
上一篇: 古代的“榻”是干什么的?魏晋南北朝时期“凳子”的替代品!
下一篇: HTML5新增的元素总结