[.NET] 利用 async & await 的异步编制程序

选用 async & await 的异步编制程序

【博主】反骨仔    【出处】http://www.cnblogs.com/liqingwen/p/5922573.html   

目录

 

一、异步编制程序的简单介绍

  通过运用异步编制程序,你能够避免品质瓶颈并升高你的应用程序的总体响应技术。

  从
VS 二零一一 初始,新引入了一个简化的法门,称为异步编制程序。大家在 >= .NET
4.5 卯月 Windows 运转时中动用异步,编写翻译器它会扶助了大家减少了一度实行的高难度异步代码编写的劳作,但逻辑结构却周边于同台代码。因而,大家仅必要举办一小部分编制程序的工作就能够获得异步编程的持有优点。

 

二、异步进步响应手艺

  异步对大概孳生短路的移动(如访谈Web 时),对
Web 能源的拜访有的时候过慢或推迟过高。若这种任务在同步进度中受阻,则整个应用程序必须等待响应完成。 在使用异步的长河中,大家的应用程序可继续实行不依赖Web
财富的其余工作,并会直接等候绿灯的职务顺遂完毕。

  那是局部卓尔不群的选取异步的使用场景,以及部分在
.NET >= 4.5 后新扩张的类库。

图片 1

  全数与用户界面相关的操作常常分享二个线程,所以利用异步对于使用 UI
线程的 App 来讲是相当重大的。

  若是说你的 App
全体操作都是一齐的,也正是说,当一个线程出现堵塞,另外线程都会现出堵塞,更要紧的是,
App 会甘休响应。

图片 2

 

  使用异步方法时,App
将承接响应
UI。如:最大和最小化,不过效果依旧在后台施行(如:下载)。

 

三、更易于编写的异步方法

  C#
中的 async 和 await 关键字都以异步编制程序的基本。通过利用那五个第一字,我们就足以在
.NET 轻便创立异步方法。

  示例:

 1         /// <summary>
 2         /// 异步访问 Web 
 3         /// </summary>
 4         /// <returns></returns>
 5         /// <remarks>
 6         /// 方法签名的 3 要素:
 7         ///     ① async 修饰符
 8         ///     ② 返回类型 Task 或 Task<TResult>:这里的 Task<int> 表示 return 语句返回 int 类型
 9         ///     ③ 方法名以 Async 结尾
10         /// </remarks>
11         async Task<int> AccessTheWebAsync()
12         {
13             //记得 using System.Net.Http 哦
14             var client = new HttpClient();
15 
16             //执行异步方法 GetStringAsync
17             Task<string> getStringTask = client.GetStringAsync("http://www.google.com.hk/");
18 
19             //假设在这里执行一些非异步的操作
20             Do();
21 
22             //等待操作挂起方法 AccessTheWebAsync
23             //直到 getStringTask 完成,AccessTheWebAsync 方法才会继续执行
24             //同时,控制将返回到 AccessTheWebAsync 方法的调用方
25             //直到 getStringTask 完成后,将在这里恢复控制。
26             //然后从 getStringTask 拿到字符串结果
27             string urlContents = await getStringTask;
28 
29             //返回字符串的长度(int 类型)
30             return urlContents.Length;
31         }

 

  如若 AccessTheWebAsync 在调用 GetStringAsync() 时未有其它操作(如:代码中的
Do()),你可以用这么的方法来简化代码。

string urlContents = await client.GetStringAsync("http://www.google.com.hk/");

  

  轻松计算:

  (1)方法签字包涵二个 async 修饰符。

  (2)依照预定,异步方法的称号供给以“Async”后缀为终极。

  (3)3
种回到类型:

    ① Task<TResult>:返回
TResult 类型。

    ②
Task:未有重回值,即再次回到值为 void。

    ③
void:只适用于异步事件管理程序。

  (4)方法一般富含至少四个await
表明式,该表明式标志一个点,大家能够成为悬挂点,在该点上,直到等待的异步操作完毕,之后的办法技艺继续执行。
与此同一时间,该措施将挂起,并将调控权重返到格局的调用方。

  

  需求利用异步方法的话,我们直接在系统里头使用所提供的要害字
async 和 await 就足以了,剩余的别的业务,就留给编写翻译器吧。 

 

四、异步方法的调整流(主题)

  异步编制程序中最重要却不易懂的是调控流,即差别方式间的切换。未来,请用一颗感恩的心来阅览下图。

图片 3

  步骤剖判:

  ① 事件处理程序调用并等候 AccessTheWebAsync() 异步方法。

  ② AccessTheWebAsync
创设 HttpClient 对象并调用它的 GetStringAsync 异步方法来下载网址内容。

  ③
要是 GetStringAsync 中发出了某种景况,该景况挂起了它的经过。或然必须等待网址下载或部分别的阻塞的位移。为幸免阻塞财富,GetStringAsync() 会将调整权出让给其调用方 AccessTheWebAsync。GetStringAsync 重临 Task,其中 TResult
为字符串,何况 AccessTheWebAsync 将职务分配给 getStringTask 变量。该职务表示调用 GetStringAsync 的正在开始展览的经过,当中承诺当工作做到时发出实际字符串值。

  ④ 由于并未等待 getStringTask,因而,AccessTheWebAsync 能够继续实践不借助于于 GetStringAsync 得出最终结果的别的职务。该职责由对一同方法 DoIndependentWork 的调用表示。

  ⑤ DoIndependentWork 是做到其行事并回到其调用方的联合方法。

  ⑥ AccessTheWebAsync 已做到职业,能够不受 getStringTask 的结果影响。 接下来,AccessTheWebAsync 须要计算并赶回该下载字符串的长短,但该措施仅在颇具字符串时能力揣测该值。由此,AccessTheWebAsync 使用八个 await
运算符来挂起其速度,并把调整权交给调用 AccessTheWebAsync 的方法。AccessTheWebAsync 将 Task<int> 再次来到至调用方。 该任务表示对爆发下载字符串长度的子弹头结果的二个承诺。

  【备注】假设 GetStringAsync(即 getStringTask)在 AccessTheWebAsync 等待前产生,则调节权会保留在 AccessTheWebAsync 中。 要是异步调用进程(getStringTask) 已成功,而且 AccessTheWebSync
不必等待最后结出,则挂起接下来回到到 AccessTheWebAsync,但那会促成基金的浪费。

  在调用方内部(假若那是叁个事件管理程序),管理情势将三番五次。在守候结果前,调用方可以开始展览不依赖于 AccessTheWebAsync 结果的其他专门的学问,不然就需拭目以俟片刻。事件管理程序等待 AccessTheWebAsync,而 AccessTheWebAsync 等待 GetStringAsync。

  ⑦ GetStringAsync 完结并生成四个字符串结果。 字符串结果不是由此你预期的艺术调用 GetStringAsync 所再次回到的。(请记住,此方法已在步骤 3
中回到四个任务。)相反,字符串结果存储在代表完毕章程 getStringTask 的职务中。 await
运算符从 getStringTask 中寻觅结果。赋值语句将寻觅到的结果赋给 urlContents。

  ⑧ 当 AccessTheWebAsync 具备字符串结果时,该措施能够总结字符串长度。然后,AccessTheWebAsync 职业也将幸不辱命,何况等待事件管理程序可继续接纳。 

 

  你可以尝试思索一下联机行为和异步行为之间的距离。当其行事成功时(第
5 步)会重回二个共同方法,但当其行事挂起时(第 3 步和第 6
步),异步方法会再次来到八个职分值。在异步方法最后成功其行事时,职务会标识为已成功,而结果(假若有)将积累在职责中。

 

五、异步中的线程

  异步方法目的在于成为非阻塞操作。异步方法中的
await 表达式在守候的职责实施的还要不会堵塞当前线程。相反,await
表达式在继续实施时办法的其他部分并将控制权重返到异步方法的调用方。

  async 和 await
关键字不会促成成立别的线程。因为异步方法不会在其自己线程上运营,因而它没有须求二十四线程。唯有当方法处于活动状态时,该办法就要时下一块上下文中运作并动用线程上的时间。能够动用 Task.Run 将占用大批量CPU
的干活移到后台线程,不过后台线程不会支持正在等候结果的经过变为可用状态。

  对于异步编制程序来讲,该基于异步的方法优于大致各样用例中的现成措施。具体来讲,此措施比 BackgroundWorker 更适用于
IO 绑定的操作,因为此代码更简便易行且不要求防备超过争用标准。结合 Task.Run()
使用时,异步编制程序比 BackgroundWorker 更适用于 CPU
绑定的操作,因为异步编制程序将运转代码的和谐细节与 Task.Run 传输至线程池的办事分别开来。

 

六、async 和 await 修饰符

  当您利用 async 修饰符钦点该方法为异步方法时:

  • 能够应用 await 来钦点悬挂点。await
    运算符会告诉编写翻译器,异步方法唯有直到等待的异步进度实行到位,技能承袭透过该点往下推行。相同的时候,调节权将再次来到至异步方法的调用方。await
    表明式中异步方法在挂起后,要是该措施还尚无实行到位并脱离,finally 块中的将不会实施。

  • 标识的异步方法本身可以透过调用它的措施进行等待。异步方法中一般包蕴多少个或多少个await 运算符,当然,二个 await
    说明式都不设有也不会招致编写翻译器错误,然而编译器会生出警告,该措施在进行的时候依然会安分守己同步方法来实践,async
    其实只是叁个标志的效益而已,告诉编写翻译器他“应该”是一个异步方法。

 

七、重返类型和参数音讯

  在编排异步方法时,大家多方会动用
Task 和 Task<TResult> 作为重返类型。

 

  示例:

 1         static async Task<Guid> Method1Async()  //Task<Guid>
 2         {
 3             var result = Guid.NewGuid();
 4 
 5             await Task.Delay(1);
 6 
 7             //这里返回一个 Guid 的类型
 8             return result;
 9         }
10 
11         static async Task Method2Async()  //Task
12         {
13             //Do...
14 
15             await Task.Delay(1);
16 
17             //Do...
18 
19             //这里没有 return 语句
20         }

 1             //调用 Method1Async
 2             //方式一
 3             Task<Guid> t1 = Method1Async();
 4             Guid guid1 = t1.Result;
 5 
 6             //方式二
 7             Guid guid2 = await Method1Async();
 8 
 9             //调用 Method2Async
10             //方式一
11             Task t2 = Method2Async();
12             await t2;
13 
14             //方式二
15             await Method2Async();

  各种再次回到的任务表示正在展开的办事。任务可包裹有关异步进度意况的音信,假若未中标,则最终会卷入来自进度的最终结果,或然是由该进度引发的不胜。

 

  【疑问】那么
void 再次来到类型是在怎么情况下才使用的呢?

  首要用于异步的事件管理程序,异步事件管理程序常常作为异步程序的初阶点。void
重临类型告诉了编写翻译器,不必要对他张开等待,並且,对于 void
重回类型的艺术,大家也无力回天对他开始展览极其的捕捉。

 

  异步方法不可见在参数中扬言与行使
ref 和 out 关键字,可是异步方法能够调用包涵那一个参数的主意。

 

八、命名的预约

  依照约定,使用
async 的方法都应有以“Async”作为后缀,如:DownloadAsync() 。可是,假若某一约定中的事件、基类或接口有其余的样式约定,则足以忽略上述约定。举例,不应该修改或重命名常用事件管理程序,如 btnOpen_Click。

 

传送门 

  1. 走进异步编制程序的世界 – 开端接触
    async/await
    (推荐)

  2. 走进异步编制程序的世界 –
    分析异步方法(上)

  3. 走进异步编制程序的社会风气 –
    剖判异步方法(下)

  4. 走进异步编制程序的世界 – 在 GUI
    中施行异步操作

 


【参谋援引】微软官方文书档案图片

【参考】https://msdn.microsoft.com/zh-cn/library/windows/apps/hh191443(v=vs.110).aspx

 

相关文章