考虑到直接讲实现一个类t群名大全ask库思维有点跳跃,所以本节主要讲解async/await的本质作用(解决了什么问题),以及async/await的工作原理。实现一个类task的库则放在后面讲。首先回顾一下的场景。
在onmou_down这个处理函数中,我们使用task的continuewith函数进行链式操作,解决了回调地狱问题,但是总感觉有点那么不爽,我们假想有个关键字await它能实现以下作用:首先await必须是task类型,必须是task类型的(其实不是必要条件,后面会讲到)原因是保证必须有continuewith这个函数,如果task没有返回值,则把await后面的代码放到task中的continuewith函数体内,如果有返回值,则把await后的结果转化为访问task.result属性,文字说的可能不明白,看下示例代码
看起来不错,但至少有以下问题,如下:
该种转换方法不能很好的转换try/catch结构在循环结构中使用await不好转换该实现与task类型紧密联系一二点是我自己认为的,但第三点是可以从扩展async/await这点被证明的。但无论怎样,async/await只是对方法按照一定的规则进行了变换而已,它并没有什么特别之处,具体来讲,就是把await后面要执行的代码放到一个类似continuewith的函数中,在c#中,它是以状态机的形式表现的,每个状态都对应一部分代码,状态机有一个movenext()方法,movenext()根据不同的状态执行不同的代码,然后每个状态部分对应的代码都会设置下一个状态字段,然后把自身的movenext()方法放到类似continuewith()的函数中去执行,整个状态机由回调函数推动。我们尝试手动转换以下async/await方法。
去桂林游 手动写一个简单的状态机类
而test()方法则变成了这样
注意test()方法返回的是void,这意味这调用方将不能await test()。如果返回task,这个状态机类是不能正确处理的,如果要正确处理,那么状态机在start()启动后,必须返回一个task,而这个task在整个状态机流转完毕后要变成完成状态,以便调用方在该task上调用的continuewith得以继续执行,而就task这个类而言,它是没有提供这种方法(内部有,但没有对外暴露)来主动控制task的状态的,这个与js中的promi不同,js里面用reslove函数来主动控制promi的状态,并导致在该promi上面的then链式调用得以继续完成,而在c#里面怎么做呢?既然使用了状态机来实现async/await,那么在转换一个返回task的函数时肯定会遇到,怎么处理写人作文300字?后面讲。
首先解决一下与task类型紧密联系这个问题。
从状态机中可以看到,主要使用到了task中的continuewith这个函数,它的语义是在任务完成后,执行回调函数,通过回调函数拿到结果,这个编程风格也叫做cps(continuation-passing-style, 续体传递风格),那么我们能不能把这个函数给抽象出来呢?语言开发者当然想到了,它被抽象成了一个awaiter因此编译器要求await的类型必须要有getawaiter方法,什么样的类型才是awaiter呢?编译器规定主要实现了如下几个方法的类型就是awaiter:
第一点好理解,第二点的作用是热路径优化,第三点以后讲。我们再改造一下我们手动写的状态机。
可以看到去掉了与task中continuewith的耦合关系,并且如果任务已经完成,则可以直接执行下个任务,避免了无用的开销。
因此我们可以总结一下async/await:
第一点我们可以用以下例子来证明,有兴趣的朋友可以自己去验证以下,以便加深理解。
一个测试函数,注意必须返回void
可以看到这是完全同步进行的。
到此这篇关于c#异步编程由浅入深(二)之async/await的作用.的文章就介绍到这了,更多相关c#异步编程async/await内容请搜索www.887551.com五言绝句古诗以前的文章或继续浏览下面的相关文章希望大家以后多多怎么记笔记支持www.887551.com!
本文发布于:2023-04-06 01:04:13,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/c1746af8bb335c1d4e4d6a14675c730a.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:C#异步编程由浅入深(二)之Async/Await的使用.doc
本文 PDF 下载地址:C#异步编程由浅入深(二)之Async/Await的使用.pdf
留言与评论(共有 0 条评论) |