C#中的async和await关键字是异步编程的核心。通过使用这两个关键字,你可以使用 .NET Framework 或者运行时的资源来创造异步方法——几乎和你写同步方法一样。你通过使用async和await定义的方法就相当于异步方法。
// 在方法签名中需要注意的三个地方:
// - 方法必须有async修饰.
// - 返回类型必须是Task或者Task<T>(看 "Return Types" 小节.)
// 这里是Task<int>因为返回声明返回了一个整型.
// - 方法名以async结尾
async Task<int> AccessTheWebAsync()
{
// 你需添加一个对System.Net.Http的引用来声明client
HttpClient client = new HttpClient();
// GetStringAsync方法返回一个Task<string>.这个意味着当你await这个
// 任务的时候,你会得到一个string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// 你可以完成一些不依赖GetStringAsync方法返回的字符串的任务
DoIndependentWork();
// await操作符中止了AccessTheWebAsync方法.
// - AccessTheWebAsync 无法继续知道 getStringTask 完成.
// - 与此同时,控制器返回AccessTheWebAsync的调用.
// - 当 getStringTask 完成的时候,控制器继续进行任务.
// - await操作符获得getStringTask返回的字符串.
string urlContents = await getStringTask;
// 返回声明指定了一个整型结果
// 任何awaiting AccessTheWebAsync的方法都会得到这个长度值
return urlContents.Length;
}
- 方法签名包含
async
修饰符 - 异步方法名称按照惯例以Async结尾
- 返回值是以下几种类型之一:
- Task:如果你的方法包含一个操作符是TResult的返回声明
- Task :如果你的方法没有任何返回值或者返回声明里面没有操作符
- Void:如果你在写一个异步事件句柄
- 方法通常包含至少一个await表达式,这个await在方法标记了一个方法无法继续执行,直到需要等待的方法完成的点。在这个等待期间,方法是被暂停着的,控制器返回到方法的调用者。下一个小节会介绍这个暂停点都发生了什么。
async和await
如果你使用async修饰符来定义一个方法的话,方法就具有以下两个功能:
- 异步方法可以使用await来指定一个等待点。await操作符告诉编译器这个异步方法不能通过,直到需要等待的方法执行完毕。与此同时,控制器返回到该方法调用者。
async方法中的await造成的停止,不会导致方法的推出,并且finally语句块不会执行。
- 异步方法可以被调用它的方法await
一个异步方法通常包含一个或者多个await操作符,但是await操作符就算不存在也不会造成编译错误。如果一个异步方法没有使用await操作符的话,整个方法就会和同步方法一样,除了有一个async操作符。编译器会对这个方法发出一个警告。
返回值类型和参数
在.NET Framework中一个异步方法一般会返回一个Task 或者一个 Task类型。在异步方法中,一个await操作符应用在一个从其他异步方法返回的任务中。
如果方法包含指定了TResult类型的
return 声明,你可以定义一个Task作为返回值。
如果你的方法没有返回声明或者声明中不返回操作符,你可以使用Task作为返回值。
每一个返回的task都代表一个正在进行的工作。一个task包括了这个异步方法的运行状态和最终的结果或者抛出的异常。
一个异步方法也可以有一个void的返回类型。这个返回类型主要在定义事件句柄的时候用到,对于定义事件句柄,void的返回类型是必须的。异步事件句柄经常作为异步程序的起点。
一个void返回类型的异步方法不能被await并且这个方法的调用者不能捕获这个方法抛出的异常。