.Net async

概述



先吐个槽,.NET的TPL框架,以及这篇文章想要表述的async await关键字,都是.NET语言层面本身支持的一种异步框架,代表其在编译时是可以最大化的被优化,作为内部DSL来说,.NET一直是非常优秀的一个平台,有的语言只是在设计模式层面提供了内部DSL的框架,在优化上肯定是不及这种语言层面支持的机制。期待它在未来的升级,例如和Go语言中的Goroutine一样,包装了线程、协程的机制自动调度。

目前有很多流行的开源框架,在架构的运行视图中,都是采用了线程池做异步的实现,是粒度的变更,例如原来ASP.NET是单线程处理一个请求,发展到了现在可以由开发人员通过async await自己来定义线程池处理的粒度,通过细粒度或者说是开发人员自定义粒度的线程池中线程切换做到自定义的并行计算与吞吐量的上升。

测试async await的场景



代码如下

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5
 6             Master();
 7
 8             Console.ReadKey();
 9         }
10
11
12         private static void Master()
13         {
14             Task task1 = SlaveWebContent1("http://www.163.com");
15
16             Task task2 = SlaveWebContent2("http://www.sina.com");
17
18             Task task3 = SlaveWebContent3("http://www.tencent.com");
19
20             Task.WaitAll(task1, task2, task3);
21         }
22
23         private static async Task<string> SlaveWebContent1(string url)
24         {
25             WebClient webClient = new WebClient();
26             string webContent=await webClient.DownloadStringTaskAsync(url);
27
28             return webContent;
29         }
30
31         private static async Task<string> SlaveWebContent2(string url)
32         {
33             WebClient webClient = new WebClient();
34             string webContent = await webClient.DownloadStringTaskAsync(url);
35
36             return webContent;
37         }
38
39         private static async Task<string> SlaveWebContent3(string url)
40         {
41             WebClient webClient = new WebClient();
42             string webContent = await webClient.DownloadStringTaskAsync(url);
43
44             return webContent;
45         }

在并行计算中,我们并不总是能恰到好处的全部采用并行的方式,所以粒度是需要可以自我定义的,async await这对关键字以方法作为载体实现了粒度的掌控。

在代码中SlaveWebContent方法应该是1个,不过为了我们来看看线程的运行模式,所以写了3个。

让我们来运行吧。

我们可以理解为主线程ID为17248。

进入了第一个方法,仍然是17248,在下面的2,3方法中,只要是在关键字await之前的代码都会是17248这个ID的线程在运行。

来看看await执行后的代码。

这里是方法3首先返回结果,因为是异步的,我们无法知道多久会返回,线程ID为13892。

方法2返回了结果,线程ID为14776。

最后是方法1返回结果,线程ID也会不一样。让我们直接跳到Master方法中WaitAll方法。

回到了主线程。

这样就执行完了整个程序。对我们来说,在每一个Slave方法内,await关键字就像一个分隔符一样,之前的代码是调用该方法的线程,await之后是将结果带回来的线程,await执行的方法是异步的,在.NET平台下,例如我们程序中的例子,实际上是调用了线程中的IO线程去下载网页内容,IO线程会怎么做呢,我没有往下看,不过我们也可以猜测一下,Reactor或者Proactor,Widnows提供了IOCP来作为非阻塞套接字的实现方式,也许是使用了这种方式。也许是这样吧,不过我们不用关心,我们只专注于await这里即可。

总结



如果结合目前很火的事件驱动,那么通过线程来实现的并发或者并行,对吞吐量是很大的提升。ASP.NET中目前也是采取的这种方式,接收到请求后,将请求投递至Worker线程池,Worker线程池将请求投递至用户处理线程池,大概是这样,用词不准确,粒度上划分就是2个大的职责,进入我们的代码中之后,我们是可以通过async await关键字将粒度再细分,这才是获得吞吐量的关键。当await处理完毕后,将处理带回来的线程将结果投递至调用的线程后,回归线程池去处理其他的事情,也许是新请求,也许是其他方法。

粒度的可操作性很大,所以也会带来一些问题,究竟我们什么时候使用它,对于短时的操作,同步性能会更好并且语义上更直观;对于要用到IO的操作,使用async await肯定是最好的场景;对于超长时的操作,自定义线程单独跑肯定是最好的,不会妨碍线程池的线程处理其他请求,线程池中的线程应该是处理时长合适的场景,时长合适就是我们的粒度选择是否合适的问题,需要在实际项目中进行测试,所以在合适的入口选择使用async aswait,在后续操作中审时使用同步。

也许在未来,会不会也会出现类似于CPU的投机运行机制呢,呵呵,很期待。

时间: 2024-11-03 22:10:52

.Net async的相关文章

async(await)函数和 Generator 函数 区别

async 函数是 Generator 函数的语法糖. async 函数对 Generator 函数的改进体现在: 1. async 内置执行器. Generator 函数的执行必须靠执行器,需要调用 next() 方法,或者用co 模块:而 async 函数自带执行器.也就是说,async 函数的执行与普通函数一模一样,只要一行. 2. 更好的语义. async 和 await 比起星号和 yield,语义更清楚. 3.更广的适用性. co 模块约定,yield 命令后面只能是 Thunk 函

Spring中@Async用法总结

 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3.x之后,就已经内置了@Async来完美解决这个问题,本文将完成介绍@Async的用法. 1.  何为异步调用? 在解释异步调用之前,我们先来看同步调用的定义:同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果. 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕:而是继续

(转)Spring中@Async用法总结

 原文:http://blog.csdn.net/blueheart20/article/details/44648667 引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spring 3.x之后,就已经内置了@Async来完美解决这个问题,本文将完成介绍@Async的用法. 1.  何为异步调用? 在解释异步调用之前,我们先来看同步调用的定义:同步就是整个处理过

async

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

Python 3.5的async和await特性(PEP492翻译)

原因: 1,coroutine容易与正常的generators弄混 2,一个function是否为coroutine由函数体内是否有yield 或者yield from 决定,这不科学. 3,如果在语法上允许yield的地方才能进行异步调用,那诸如with和for语句中都不能执行异步了. 咋解决呢,把coroutine当成一个native的Python语言特性,与generator完全独立. Native coroutines及其新的语法使得在异步条件下定义context manager(上下文

ASP.NET WebForm中用async/await实现异步出人意料的简单

1. 在.aspx中添加异步标记 <%@ Page Language="C#" Async="true"%> 2. 在.aspx.cs或者.ascx.cs(用户控件)中添加异步方法 private async Task GetMyPosts() { var posts = await ServiceFactory.BlogPostSevice.GetBlogPostsPagedAsync(); rpPosts.DataSource = posts; rp

ajax返回的值有两种方法,一种是把async:true改为false。 另一种是回调函数。

function load_val(callback){//定义一个回调函数 $.getJSON('test.php' , function(dat){ callback(data);//将返回结果当作参数返回 }); } load_val(function(data){ alert(data);//这里可以得到值 }); //否则的话你需要这样用同步ajax来实现了 function load_val2(){ var result; $.ajax({ dataType:'json', url

Javascript中的async await

async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案.目前,async / await这个特性已经是stage 3的建议,可以看看TC39的进度,本篇文章将分享async / await是如何工作的,阅读本文前,希望你具备Promise.generator.yield等ES6的相关知识. 在详细介绍async / await之前,先回顾下目前在ES6中比较好的异步处理办法.下面的例子中数据请求用Node.js中的request模块,数据接口采用Github v3

js-ES6学习笔记-async函数(3)

1.await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中. 2.多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发. // 写法一 let [foo, bar] = await Promise.all([getFoo(), getBar()]); // 写法二 let fooPromise = getFoo(); let barPromise = getBar(); let foo = await

ajax中的async设置问题

问题: 当项目启动登录后,google浏览器(F12)或fireFox等浏览器会出现如下警告: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.     jquery-1.8.0.min.js:2 For more help, check https://xhr.spec.whatwg.org/.