async and await 的入门基础操作
如果有几个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;
}
相关文章
- 这篇文章主要介绍了C#异步的世界(下),对异步感兴趣的同学,可以参考下...2021-04-26
- 这篇文章主要介绍了ASP.Net中的async+await异步编程的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
- 这篇文章主要介绍了Spring @Async无法实现异步的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-02
详解C#中 Thread,Task,Async/Await,IAsyncResult的那些事儿
本文主要介绍了C#中 Thread,Task,Async/Await,IAsyncResult的相关知识。具有一定的参考价值,下面跟着小编一起来看下吧...2020-06-25- 这篇文章主要介绍了关于async和await的一些误区实例详解,有助于更加深入的理解C#程序设计,需要的朋友可以参考下...2020-06-25
- 本篇文章主要介绍了说说C#的async和await的具体用法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- 这篇文章主要介绍了浅谈C#中的Async和Await的用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
python实习总结(yeild,async,azwait和协程)
今天是Python实习的第一天,熟悉了环境,第一次使用macbook,氛围还不错,努力学习新知识,希望本片文章能给你带来帮助...2021-10-08- 这篇文章主要介绍了如何在Express4.x中愉快地使用async的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-18
- 这篇文章主要给大家介绍了如何通过一篇文章弄懂C#中async和await的相关资料,async和await相信大家应该不陌生,让异步处理变得更友好,本文通过示例代码介绍的非常详细,需要的朋友可以参考下...2021-07-01
- 这篇文章主要介绍了ASP.NET 应用程序实际使用过程中的一些总结, 包括 异常捕获 、 死锁 、 应用程序崩溃 ,实际使用过程中一不注意就可能掉坑里了...2021-09-22
- async表示异步,而await可以看作async wait,个人对async与await的简单理解就是,我们可以用同步的方式去书写异步代码,这篇文章主要给大家介绍了关于JS中如何优雅的使用async await的相关资料,需要的朋友可以参考下...2021-10-05
.NET中的async和await关键字使用及Task异步调用实例
这篇文章主要介绍了.NET中的async和await关键字使用及Task异步调用实例,本文还包含了取消执行和显示进度的例子,需要的朋友可以参考下...2020-06-25- 这篇文章主要介绍了c# Async streams的使用解析,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...2021-04-24
.NET Core控制台应用程序如何使用异步(Async)Main方法详解
这篇文章主要给大家介绍了关于.NET Core控制台应用程序如何使用异步(Async)Main方法的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22- 这篇文章主要介绍了c# 在Emit代码中如何await一个异步方法,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...2021-03-23
浅谈Async和Await如何简化异步编程(几个实例让你彻底明白)
本篇文章主要介绍了浅谈Async和Await如何简化异步编程,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25- 这篇文章主要介绍了C#中的Async和Await用法,包括在C#5.0下一些新特性的影响,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了Java Spring之@Async原理案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...2021-09-02
- 本篇文章对async and await 的入门基础操作进行了详细的分析介绍,需要的朋友参考下...2020-06-25