msdn介绍:https://msdn.microsoft.com/zh-cn/library/hh191443.aspx
其实很简单,标记了async的方法为异步方法,从方法的左大括号开始同步执行,直到第一个await出现就开始异步执行,主线程等待,等带await这行代码异步完了再回到主线程,然后继续往下执行。
如果后面又遇到带await语句的,又异步执行,执行完了就回来,继续同步往下。依此类推。
这样做其实就把我们以前编写等待句柄接收信号的代码给省掉了,就一个await就搞定。
Visual Basic 中的 Async 和 Await 关键字,以及 C# 中的 async 和 await 关键字都是异步编程的核心。 通过使用这两个关键字,你可以使用 .NET framework 或 Windows 运行时中的资源轻松创建异步方法(几乎与创建同步方法一样轻松)。 通过使用被称为异步方法的 async 和 await 定义的异步方法。
以下特征总结了使上一个示例成为异步方法的原因。
- 方法签名包含一个 Async 或 async 修饰符。
- 按照约定,异步方法的名称以“Async”后缀为结尾。
- 返回类型为下列类型之一:
- 如果你的方法有操作数为 TResult 类型的返回语句,则为 Task<TResult>。
- 如果你的方法没有返回语句或具有没有操作数的返回语句,则为 Task。
- 如果你编写的是异步事件处理程序,则为 Void(Visual Basic 中为 Sub)。
有关详细信息,请参见本主题后面的“返回类型和参数”。
- 方法通常包含至少一个 await 表达式,该表达式标记一个点,在该点上,直到等待的异步操作完成方法才能继续。 同时,将方法挂起,并且控件返回到方法的调用方。 本主题的下一节将解释悬挂点发生的情况。
在异步方法中,可使用提供的关键字和类型来指示需要完成的操作,且编译器会完成其余操作,其中包括持续跟踪控件以挂起方法返回等待点时发生的情况。 一些常规流程(例如,循环和异常处理)在传统异步代码中处理起来可能很困难。 在异步方法中,元素的编写频率与同步解决方案相同且此问题得到解决。
关系图中的数值对应于以下步骤。
- 事件处理程序调用并等待 AccessTheWebAsync 异步方法。
- AccessTheWebAsync 可创建 HttpClient 实例并调用 GetStringAsync 异步方法以下载网站内容作为字符串。
- GetStringAsync 中发生了某种情况,该情况挂起了它的进程。 可能必须等待网站下载或一些其他阻止活动。 为避免阻止资源,GetStringAsync 会将控制权出让给其调用方 AccessTheWebAsync。
GetStringAsync 返回 Task<TResult>,其中 TResult 为字符串,并且 AccessTheWebAsync 将任务分配给 getStringTask 变量。 该任务表示调用 GetStringAsync 的正在进行的进程,其中承诺当工作完成时产生实际字符串值。
- 由于尚未等待 getStringTask,因此,AccessTheWebAsync 可以继续执行不依赖于 GetStringAsync 得出的最终结果的其他工作。 该任务由对同步方法 DoIndependentWork 的调用表示。
- DoIndependentWork 是完成其工作并返回其调用方的同步方法。
- AccessTheWebAsync 已用完工作,可以不受 getStringTask 的结果影响。 接下来,AccessTheWebAsync 需要计算并返回该下载字符串的长度,但该方法仅在具有字符串时才能计算该值。
因此,AccessTheWebAsync 使用一个 await 运算符来挂起其进度,并把控制权交给调用 AccessTheWebAsync 的方法。 AccessTheWebAsync 将 Task(Of Integer) 或 Task<int> 返回至调用方。 该任务表示对产生下载字符串长度的整数结果的一个承诺。
注意
如果 GetStringAsync(因此 getStringTask)在 AccessTheWebAsync 等待前完成,则控件会保留在 AccessTheWebAsync 中。 如果异步调用过程 (AccessTheWebAsync) 已完成,并且 AccessTheWebSync 不必等待最终结果,则挂起然后返回到 getStringTask 将造成成本浪费。在调用方内部(此示例中的事件处理程序),处理模式将继续。 在等待结果前,调用方可以开展不依赖于 AccessTheWebAsync 结果的其他工作,否则就需等待片刻。 事件处理程序等待 AccessTheWebAsync,而 AccessTheWebAsync 等待 GetStringAsync。
- GetStringAsync 完成并生成一个字符串结果。 字符串结果不是通过按你预期的方式调用 GetStringAsync 所返回的。 (记住,该方法已返回步骤 3 中的一个任务)。 相反,字符串结果存储在表示完成 getStringTask 方法的任务中。 await 运算符从 getStringTask 中检索结果。 赋值语句将检索到的结果赋给 urlContents。
- 当 AccessTheWebAsync 具有字符串结果时,该方法可以计算字符串长度。 然后,AccessTheWebAsync 工作也将完成,并且等待事件处理程序可继续使用。 在此主题结尾处的完整示例中,可确认事件处理程序检索并打印长度结果的值。
如果你不熟悉异步编程,请花 1 分钟时间考虑同步行为和异步行为之间的差异。 当其工作完成时(第 5 步)会返回一个同步方法,但当其工作挂起时(第 3 步和第 6 步),异步方法会返回一个任务值。 在异步方法最终完成其工作时,任务会标记为已完成,而结果(如果有)将存储在任务中。