欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

新时尚Windows8开发(35):后台传输

程序员文章站 2023-02-20 08:47:51
所谓后台传输,关键是突出在,在应用程序不在前台运行时,它仍然可以进行数据传输,一般而言,这个功能用于下载文件比较适合,像“应用商店”的下载应用就是使用了后台传输。 这个后台传...

所谓后台传输,关键是突出在,在应用程序不在前台运行时,它仍然可以进行数据传输,一般而言,这个功能用于下载文件比较适合,像“应用商店”的下载应用就是使用了后台传输。

这个后台传输当然包括下载和上传了,不过,我想是下载的情况会多一些,呵呵,不知道是不是这样,元芳,你怎么看?

好了,不管元芳怎么看了,首先大家做好心理准备,接下来我会讲一点点比较枯燥的东东,不怕,只是一点点而已,我不喜欢长篇巨论,免得各位看着看着就睡觉了。

 

实现后台下载,一般有以下几步要走:

引入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的下载地址帖上去,然后点击“开始下载”,看有没有效果?如果无误,你会看到如下图所示的内容。

 

 新时尚Windows8开发(35):后台传输
新时尚Windows8开发(35):后台传输