一、await
当遇到await表达式时,通常情况下执行过程会返回到调用者上。就像是迭代器中的yield return一样。但是,运行时在返回之前会在等待的任务上附加一个延续,保证任务结束时,执行点会跳回到方法中,并继续执行剩余的代码。如果任务出错,则会重新抛出异常;如果顺利结束,则用返回值为await表达式赋值。
void Main()
{
DisplayPrimesCount();
}
//添加了async修饰符的方法称为异步函数,这是因为通常它们本身也是异步的。
async void DisplayPrimesCount()
{
int result = await GetPrimesCountAsync (2, 1000000);
Console.WriteLine (result);
}
Task<int> GetPrimesCountAsync (int start, int count)
{
return Task.Run (() =>
ParallelEnumerable.Range (start, count).Count (n =>
Enumerable.Range (2, (int)Math.Sqrt(n)-1).All (i => n % i > 0)));
}
二、async
async修饰符会指示编译器将await作为一个关键字而非标识符来避免二义性(C#5之前的代码有可能将await作为标识符,这样做可以确保之前的代码还能够正确进行编译)。async修饰符只支持返回类型为void以及(我们稍后会介绍的)Task或Task<TResult>的方法(或Lambda表达式)。
要编写异步函数,可将返回类型由void更改为Task。这样方法本身就可以进行异步调用(并且是可等待的)。
需要注意的是方法体内并不需要显式返回一个任务。编译器会负责生成任务,并在方法完成之前或出现未处理的异常时触发任务。这样就很容易创建异步调用链。
异步函数中若方法体返回TResult则函数的返回值为Task<TResult>。
async Task<int> GetAnswerToLife()
{
await Task.Delay (5000);
int answer = 21 * 2;
return answer;
}
三、总结
1、async和await关键字可以极大地降低程序的复杂性。
2、使用C#异步函数进行程序设计的基本原则:
(1)首先以同步方式实现方法。
(2)其次,将同步方法调用改为异步方法调用,并使用await。
(3)除了“最顶级”的方法(通常是UI控件事件处理器)之外,将异步方法的返回类型修改为Task或者Task<TResult> ,使其成为可等待的方法。