async、await是在C# 5.0以后引入的一种简化异步操做的方式。使用它们以后,能够使咱们的编写异步操做更加方便快捷,维护以及阅读起来更方便。api
async、await虽然简化了咱们编写异步方法。但也很容易让人产生误解。首先看一个例子:异步
public static async Task<int> AddAsync(int x, int y) { return await Task.Factory.StartNew(() => { return x + y; }); }
这种加了async、await叫不叫异步呢?答案确定不是的。咱们能够这样叫这种方法:加了async、await标记的同步方法。async
再看下面的一个例子ide
原文:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index 网站
// Three things to note in the signature: // - The method has an async modifier. // - The return type is Task or Task<T>. (See "Return Types" section.) // Here, it is Task<int> because the return statement returns an integer. // - The method name ends in "Async." async Task<int> AccessTheWebAsync() { // You need to add a reference to System.Net.Http to declare client. HttpClient client = new HttpClient(); // GetStringAsync returns a Task<string>. That means that when you await the // task you'll get a string (urlContents). Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com"); // You can do work here that doesn't rely on the string from GetStringAsync. DoIndependentWork(); // The await operator suspends AccessTheWebAsync. // - AccessTheWebAsync can't continue until getStringTask is complete. // - Meanwhile, control returns to the caller of AccessTheWebAsync. // - Control resumes here when getStringTask is complete. // - The await operator then retrieves the string result from getStringTask. string urlContents = await getStringTask; // The return statement specifies an integer result. // Any methods that are awaiting AccessTheWebAsync retrieve the length value. return urlContents.Length; }
上面的方法GetStringAsync,若是不须要返回值,能够移步进行执行,而后会执行方法DoIndependentWork方法,知道await getStringTask拿到GetStringAsync方法的返回值。ui
如下特征总结了使上一个示例成为异步方法的缘由。url
方法签名包含 async
修饰符。spa
按照约定,异步方法的名称以“Async”后缀结尾。code
返回类型为下列类型之一:blog
若是你的方法有操做数为 TResult 类型的返回语句,则为 Task<TResult>。
若是你的方法没有返回语句或具备没有操做数的返回语句,则为 Task。
Void
:若是要编写异步事件处理程序。
包含 GetAwaiter
方法的其余任何类型(自 C# 7 起)。
有关详细信息,请参见本主题后面的“返回类型和参数”。
方法一般包含至少一个 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<int>
返回给调用方。 该任务表示对产生下载字符串长度的整数结果的一个承诺。
简单一句话,并非全部的加了async和await关键字的方法就是异步方法。能够这样理解 await 的位置决定了究竟是不是异步方法,若是直接await xxxAsync那么是挂起当前方法直到拿到返回值才会执行下面的逻辑,这样就是一种同步方法了。异步是相似这样的 代码块:
task t=xxAsync(); //其它业务逻辑 await t; //结束
参考文章
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index 这篇文章对async、await介绍的很是详细,不懂的能够参考这个。