C#异步编程之 async 和 await 的用法
介绍C#异步编程之 async 和 await 的用法
一.async 和 await 概述
使用 async 关键字可将方法(包括匿名方法和lambda表达式)指定为异步。 如下示例定义了一个名为 ExampleMethodAsync 的异步方法:
public async Task<int> ExampleMethodAsync()
{
//...
}
标记的异步方法可以使用 await 关键字来指定暂停点。await 告诉编译器,在等待的异步进程完成之前,异步方法无法继续超过该点。 同时,控件将返回到异步方法的调用方。
string contents = await httpClient.GetStringAsync(requestUrl);
二.Demo1 展示和分析
自定义一个异步方法【GetUrlLengAsync】,其内调用并等待异步方法【GetStringAsync】,将返回值保存并返回。Main方法也定义为异步方法,其等待【GetUrlLengAsync】执行完成并打印时间。
using System;
using System.Threading.Tasks;
using System.Net.Http;
namespace Console0719
{
public class DelegateExample
{
static async Task<int> GetUrlLengAsync()//Task<int>:返回int,用Task<int>
{
var client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("https://learn.microsoft.com/dotnet");//调用异步方法:client.GetStringAsync
string contents = await getStringTask; //等待异步方法完成:await + 返回值
Console.WriteLine("In GetUrlLengAsync, func GetStringAsync finished:" + DateTime.Now.ToString("HH:mm:ss"));
return contents.Length;
}
static async Task Main(string[] args)//async:将方法标记为异步方法; Task:无返回值用task
{
Console.WriteLine("Before call GetUrlLengAsync:" + DateTime.Now.ToString("HH:mm:ss"));
await GetUrlLengAsync();//调用异步方法并等待:await+方法名()
Console.WriteLine("After call GetUrlLengAsync:" + DateTime.Now.ToString("HH:mm:ss"));
Console.ReadKey();
}
}
}

三.Demo2 展示和分析
自定义一个异步方法【GetUrlLengAsync】,其内调用并等待异步方法【GetStringAsync】,将返回值保存并返回。Main方法不是异步方法,不等待【GetUrlLengAsync】完成并打印时间。
using System;
using System.Threading.Tasks;
using System.Net.Http;
namespace Console0719
{
public class DelegateExample
{
static async Task<int> GetUrlLengAsync()//Task<int>:返回int,用Task<int>
{
var client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("https://learn.microsoft.com/dotnet");//保存异步方法返回值
string contents = await getStringTask; //等待异步方法完成:await + 返回值
Console.WriteLine("In GetUrlLengAsync, func GetStringAsync finished:" + DateTime.Now.ToString("HH:mm:ss"));
return contents.Length;
}
static void Main(string[] args)
{
Console.WriteLine("Before call GetUrlLengAsync:" + DateTime.Now.ToString("HH:mm:ss"));
GetUrlLengAsync();
Console.WriteLine("After call GetUrlLengAsync:" + DateTime.Now.ToString("HH:mm:ss"));
Console.ReadKey();
}
}
}

四.异步方法的精简结论和注意事项
4.1 异步方法的调用和等待结果(Demo1)
- await+方法名() (推荐)
await GetUrlLengAsync();//调用异步方法并等待:await+方法名()
- 先保存异步方法返回值,再等待异步方法完成:await + 返回值
Task<string> getStringTask = client.GetStringAsync("https://learn.microsoft.com/dotnet");//保存异步方法返回值
string contents = await getStringTask; //等待异步方法完成:await + 返回值
4.2 用 async 修饰 main 方法(Demo1)
Main 可以返回 void、 int、 Task或 Task<int>,仅当Main返回Task或Task<int>时,可以用 async 修饰 main
4.3 在调用处不等待异步方法完成的情形(Demo2)
异步方法调用后的逻辑和异步方法返回值无关时,在调用处可不等待异步方法执行完成
4.4 异步方法不包含await的情况
如果 async 关键字修改的方法不包含 await,该方法将同步执行。 编译器不会报错,会发出警告
4.5 命名约定
按照惯例,返回常见可等待类型的方法(例如,Task、Task<T>、ValueTask、ValueTask<T>)应具备以“Async”结尾的名称。 启动异步操作但不返回可等待类型的方法,不应具有以“Async”结尾的名称,但可能以“Begin”、“Start”或其他一些动词开头,表明此方法不会返回或抛出操作的结果。
五.异步方法返回类型
异步方法可具有以下返回类型:
- Task:无返回值
- Task<TResult>:返回TResult类型
- void:仅当需要将异步方法注册到事件中时,使用void返回值
六.参考
更多推荐
所有评论(0)