在C#语言中,Async/AWait特性可以创建并使用异步方法。该特性由三个部分组成:
- 调用方法(calling method):该方法调用异步方法,然后在异步方法(可能在相同的线程也可能在不同的线程)执行任务的时候继续执行。
- 异步(Async)方法:该方法异步执行其工作,然后返回到调用方法。
- await表达式:用于异步方法内部,指明需要异步执行的任务。异步方法中可以包含任意多个await表达式,如果一个都不包含编译器会发出警告。
调用方法:
Class Program
{
static void Main()
{
...
Task<int> value = DoAsyncStuff.CalculateSumAsync(5, 6);
...
}
}
异步方法:
static class DoAsyncStuff
{
public static async Task<int> CalculateSumAsync(int i1, int i2)
{
int sum = await TakeEx.Run(()=>GetSum(i1, i2));
return sum;
}
}
如上所述,异步方法在完成工作之前即返回调用方法,然后在调用方法继续执行时完成工作。在语法上,异步方法具有如下的特点:
- 方法头中包含async方法修饰符。
- 包含一个或多个await表达式,表示可以异步完成的任务。
- 必须具备以下三种返回类型:
- void
- Task
- Task<T>
- 异步方法的参数可以为任意类型任意数量,但不能为out和ref参数。
- 安装预定,异步方法的名称应该以Async为后缀。
- 除了方法以外,Lambda表达式和匿名方法也可以作为异步对象。
方法的async关键字
- 异步方法在方法头中必须包含async关键字,且必须出现在返回类别之前。
- 该修饰符只是标识该方法包含一个或几个await表达式,也就是说,它本身并不能创建任何异步操作。
- async关键字是一个上下文关键字,也就是说除了作为方法修饰符(或Lambda表达式修饰符、匿名方法修饰符)之外,async还可用作标识符。
异步方法的返回类型
- Task<T>:如果调用方法要从调用中获取一个T类型的值,异步方法的返回值就必须是Task<T>。调用方法将通过读取Task的Result属性来获取这个T类型的值。
Task<int> value = DoStuff.CalculateSumAsync(5, 6);
...
Console.WriteLine( “Value: {0}”, value.Result);
任何返回Task<T>类型的异步方法其返回值必须为T类型或可以隐式转换为T的类型。
- Task:如果调用方法不需要从异步方法在返回值,但需要坚持异步方法的状态,那么异步方法可以返回一个Task类型的对象。这时,即使异步方法中出现return语句,也将不会返回任何东西。
Task someTask = Dostuff.CalculateSumAsync(5, 6);
...
someTask.wait();
- void:如果调用方法仅仅想执行异步方法,而不需要与它做进一步的交互时【这称为“调用并遗忘”(fire and forget)】,异步方法可以返回void类型。这时与上一种情况类似,即使异步方法中包含任何return语句,也不会返回任何东西。
例:使用返回Task<T>对象的异步方法:
using System;
using System.Threading.Tasks;
class Program
{
static void Main()
{
Task<int> value = DoAsyncStuff.CalculateSumAsync(5, 6);
// 处理其他事情…
Console.WriteLine(“Value: {0}”, value.Result);
}
}
static class DoAsyncStuff
{
public static async Task<int> CalculateSumAsync(int i1, int i2)
{
int sum=await Task.Run(()=>GetSum(i1,i2));
return sum;
}
private static int GetSum(i1, i2)
{
return i1 + i2;
}
}
例:使用返回Task对象的异步方法
using System;
using System.Threading.Tasks;
class Program
{
static void Main()
{
Task someTask = DoAsyncStuff.CalculateSumAsync(5, 6);
// 处理其他事情……
someTask.Wait();
Console.WriteLine ( “Async stuff is done”);
}
}
static class DoAsyncStuff
{
public static async Task CalculateSumAsync(i1, i2);
{
int value = await Task.Run(() => GetSum(i1, i2);
Console.WriteLine(“Value {0}”, value);
}
private static int GetSum(int i1, int i2)
{
return i1 + i2;
}
}
例:使用“调用并遗忘”的异步方法
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
DoAsyncStuff.CalculateSumAsync(5, 6);
// 处理其他事情…
Thread.Sleep(200);
Console.WriteLine(“Program Exiting”);
}
}
static class DoAsyncStuff
{
public static async void CalculateSumAsync(int i1, int i2)
{
int value = await Task.Run(() => GetSum(i1, i2);
Console.writeLine(“value: {0}, value);
}
private static int GetSum(int i1, int i2)
{
return i1 + i2;
}
}
网友评论