如果有几个Uri,需要获取这些Uri的所有内容的长度之和,你会如何做?

很简单,使用WebClient一个一个的获取uri的内容长度,进行累加。

也就是说如果有5个Uri,请求的时间分别是:1s 2s 3s 4s 5s.

那么需要的时间是:1+2+3+4+5=(6*5)/2=15.

如果采用并行计算的话,结果可能是这样:

总时间长度是5s.

为了演示效果,需要下面3个页面:

其中SlowPage 的Page_load代码如下:

protected void Page_Load(object sender, EventArgs e)
{
    Thread.Sleep(5000);
}

VerySlowPage的Page_load事件则 Thread.Sleep(10000);

新建控制台程序CAStudy:

首先新建类AsyncDemo:

同步的获取Uris的内容长度代码如下:

public class AsyncDemo
    {
        public int SumPageSizes(IList<Uri> uris)
        {
            int total = 0;
            foreach (var uri in uris)
            {
                Console.WriteLine("Thread {0}:Found {1} bytes...{2}",
                    Thread.CurrentThread.ManagedThreadId, total,DateTime.Now);
                var data = new WebClient().DownloadData(uri);
                total += data.Length;
            }
            Console.WriteLine("{0}:Found {1} bytes total {2}",
                Thread.CurrentThread.ManagedThreadId, total, DateTime.Now);
            return total;
        }
    }

在这里SumPageSizes 方法,通过foreach循环一个一个的下载数据

Main函数如下:

public static void Main()
{
    List<Uri> uris = new List<Uri>();

    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/QuickPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/SlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/VerySlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/QuickPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/SlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/VerySlowPage.aspx"));
    AsyncDemo asyncDemo = new AsyncDemo();
    int totalSize = asyncDemo.SumPageSizes(uris);
}

Main 函数主要是构造Uri,然后调用AsyncDemo的SumPageSizes方法来获取所有Uri的内容的总长度。

结果如下:

可以看到时间分别是0s,5s,10s,0s ,5s,10s.所以总长度是(0+5+10)*2=30.

可以看到速度很慢,如果有一个网页卡住的话,后面很恐怖的哦

下面演示使用async,await的方式:

第一步:将 VS2010 升级到 VS2010 sp1.

第二步:下载Async CTP,进行安装

第三步:为应用程序添加AsyncCTPLibrary引用,如下:

OK,将上面的SumPageSizes 方法修改如下:

public async Task<int> SumPageSizesAsync2(IList<Uri> uris)
{
    var tasks = uris.Select(uri => new WebClient().DownloadDataTaskAsync(uri));
    var data = await TaskEx.WhenAll(tasks);
    return await TaskEx.Run(() =>
    {
        return data.Sum(s => s.Length);
    });
}

在AsyncCTPLibrary.dll中,微软为一些类提供了扩展,如下:

WebClient的扩展如下:

可以看到基本上为每个Download 都增加了一个XXXTaskAsync 的扩展方法。

返回的全部都是Task,

为什么全部都是Task?,因为await 只能wait Task,并且await 只能用在async 标记的方法中,

async 关键字表明这是个异步方法。

第一句:

public async Task<int> SumPageSizesAsync(IList<Uri> uris)

因为我们申明的是一个异步方法,所以要使用async 关键字,SumPageSizesAsync方法返回的结果是int类型,所以返回Task<int>.

第二句:

IEnumerable<Task<Byte[]>> tasks = uris.Select(uri => new WebClient().DownloadDataTaskAsync(uri));

获取DownloadDataTaskAsync返回的所有Task。

第三句:

byte[][] data = await TaskEx.WhenAll(tasks);

首先第二句返回的是IEnumerable<Task<Byte[]>> 类型,也就是一个一个的Task<Byte[]> 的任务,使用TaskEx的WhenAll方法可以将这些任务转变成一个Task<Byte[][]> 的任务

使用await关键字意味着Task<Byte[][]> 方法需要等待,等待结束后返回Byte[][]。

第四句:

return await TaskEx.Run<int>(() =>

{

return data.Sum(s => s.Length);

});

TaskEx.Run 返回将使用第三句返回的data,将Byte[][] 的数据进行Sum运算,返回一个Task<int> 的对象,如果不使用await 的话:

因为 async 关键字代表的是异步方法,并且该异步方法返回的结果是int,所以需要再次使用await 关键字:

return await TaskEx.Run<int>(() =>

{

return data.Sum(s => s.Length);

});

修改Main代码如下:

public static void Main()
{
    List<Uri> uris = new List<Uri>();

    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/QuickPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/SlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/VerySlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/QuickPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/SlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/VerySlowPage.aspx"));
    AsyncDemo asyncDemo = new AsyncDemo();
    Console.WriteLine(DateTime.Now);
    int totalSize = asyncDemo.SumPageSizesAsync(uris).Result;
    Console.WriteLine("TotalSize:{0}, Finished", totalSize);
    Console.WriteLine(DateTime.Now);
}

运行结果如下:

可以看到使用了16秒的时间,大致等于理论值15.

有的同学会说,很麻烦!,的确,我也感觉很麻烦,还不如ThreadPool 来的快,不过async,await主要并不是解决这类问题的,它所解决的是异步中的同步,也就是说在某些异步操作中,需要同步的去处理,比如在Silverlight中,

异步获取A –> 异步获取B –> 异步获取C..

如果使用传统的方式则需要:

WebClient webClient = new WebClient();
 webClient.DownloadDataCompleted += (s, e) =>
 {
     // 使用A对象,做些事情。
     WebClient webClient2 = new WebClient();
     webClient2.DownloadDataCompleted += (s2, e2) =>
     {
         //使用B对象,做些事情。
     };
     webClient2.DownloadDataAsync(new Uri("B 的地址"));
 };
 webClient.DownloadDataAsync(new Uri("A 的地址"));

当然在这里演示的是最丑陋的版本,聪明的同学可以使用Enumerable 来简化异步操作。

如果使用async 和await则可以修改为:

public async Task<int> SumPageSizesAsync3(IList<Uri> uris)
{
    int total = 0;
    foreach (var uri in uris)
    {
        WebClient webClient=new WebClient();
        var data = await webClient.DownloadDataTaskAsync(uri);
        total += data.Length;
    }
    return total;
}

async and await 简单的入门相关推荐

  1. 一个简单的实例帮你彻底学会async和await的用法

    首先我相信很多人都知道async和await,并且知道他们可以解决异步问题,比如请求一个接口,我们下面的同步操作需要等这个接口的返回值做判断,一般我们就直接写在成功的回调里面,但是如果请求接口很多,那 ...

  2. async And await异步编程活用基础

    async And await异步编程活用基础 原文:async And await异步编程活用基础 好久没写博客了,时隔5个月,奉上一篇精心准备的文章,希望大家能有所收获,对async 和 awai ...

  3. 小程序高级电商前端第2周深入理解REST API开发规范 开启三端分离编程之旅<二>----scroll-view组件的灵活应用、async和await问题探讨、spu-scroll自定义组件

    前言: 转眼距离上一次写博文又过去一个月了,今年的博文节奏已经彻底被打破了: 真的是有心无力了,其原因在之前也提到过,组织架构调整,各种考核(跨领域性质的考核)实行末尾淘汰制,说不出的酸楚,不过换个心 ...

  4. JavaScript 异步编程--Generator函数、async、await

    JavaScript 异步编程–Generator函数 Generator(生成器)是ES6标准引入的新的数据类型,其最大的特点就是可以交出函数的执行的控制权,即:通过yield关键字标明需要暂停的语 ...

  5. C# 中的Async 和 Await 的用法详解

    众所周知C#提供Async和Await关键字来实现异步编程.在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await. 同样本文的内容也大多是翻译 ...

  6. node mysql await_node.js中对 mysql 进行增删改查等操作和async,await处理

    要对mysql进行操作,我们需要安装一个mysql的库. 一.安装mysql库 npm install mysql --save 二.对mysql进行简单查询操作 const mysql = requ ...

  7. C# 5.0中引入了async 和 await

    C# 5.0中引入了async 和 await.这两个关键字可以让你更方便的写出异步代码. 看个例子: [csharp] view plaincopy public class MyClass { p ...

  8. 多线程编程学习笔记——async和await(三)

    接上文 多线程编程学习笔记--async和await(一) 接上文 多线程编程学习笔记--async和await(二) 五.   处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...

  9. node.js中对 mysql 进行增删改查等操作和async,await处理

    要对mysql进行操作,我们需要安装一个mysql的库. 一.安装mysql库 npm install mysql --save 二.对mysql进行简单查询操作 const mysql = requ ...

  10. 【转载】 C# 中的Async 和 Await 的用法详解

    众所周知C#提供Async和Await关键字来实现异步编程.在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await. 同样本文的内容也大多是翻译 ...

最新文章

  1. c语言关闭其他进程tcp_tcp链接迁移
  2. 【Java VisualVM】使用 VisualVM 进行性能分析及调优
  3. 马哥教育第二十四ftp协议、vsftpd的高级应用、rpc概念及nfs的基本应用、samba及其基本应用...
  4. Android使用 SO 库时要注意的一些问题
  5. Redis对象的refcount与lru属性(内存回收、对象共享、空转时长)
  6. python float精度问题_Python之☞float浮点数精度问题
  7. 惠普c7000服务器装系统,HP BladeSystem c7000 安装配置手册
  8. 154.寻找旋转排序数组中的最小值II
  9. layui 之button 事件绑定的一种方法
  10. cad刷新快捷键_47个快捷键、50个CAD技巧。
  11. 商务部关于促进电子商务规范发展的意见
  12. [转载]Meta Learning单排小教学
  13. SpringBoot 集成 WebSocket 实现消息群发推送
  14. 宽带和流量是分开的吗_宽带、带宽和流量的区别
  15. python怎么关闭浏览器_/python里webbrowser怎么关闭游览器
  16. 1月5日 负数的十六进制如何表示。
  17. Beyond Compare文件对比工具中文网站来啦
  18. aria2c 使用代理下载(Use With Proxy)
  19. ET200SP CM PtP模块在STEP 7中的使用
  20. 计算机应聘大学生自我介绍,大学生计算机毕业面试自我介绍

热门文章

  1. 以一定概率执行某段代码(Python实现)
  2. Dynamic programming
  3. 刘海屏的MacBook Pro还值得入手吗?
  4. 每天一个实用小技巧!教你在Mac上共享WiFi密码
  5. 【苹果发布资讯】macOS Big Sur 11.4 正式版 – 修复漏洞和增加GPU支持
  6. Android中保存网络图片到SD卡
  7. OC中数组的遍历方法
  8. Riot v4.0.0-alpha.10 发布,JavaScript 的 MVP 框架
  9. vue路由vue-router的使用
  10. Android之MVC模式