C# 异步编程
C# 异步编程需要async
和await
关键字来进行支持。异步编程主要应用在两种模式下:
- 当程序有 IO 瓶颈时:如访问数据库、读写文件系统或者处理网络请求时,IO都是程序运行的主要瓶颈。
- 当程序有CPU性能瓶颈时:如进行大量复杂的运算,此时程序的瓶颈在于CPU的性能上。
两种模式下对应的异步编程:
1. 有IO限制的代码:需要在async
方法里面 await一个返回Task
或Task<T>
的线程。该方法不需要使用Task.Run
。
// 如点击Button获取指定网站上字符内容的长度,为了不阻塞UI需要将获取处理单独放在一个线程。
private async Task<int> GetLengthAsync()
{
var client = new HttpClient();
Task<string> GetStrTask = client.GetStringAsync("https://docs.microsoft.com/dotnet");
Console.WriteLine("Wroking....");
string resStr = await GetStrTask;
//或者合在一起的写法:
//string resStr = await client.GetStringAsync("https://docs.microsoft.com/dotnet");
return resStr.Length;
}
// 在UI上点击Button后,对应响应函数可以为Lambda匿名函数或者非匿名函数
// 1. Lambda 匿名函数方式
btn.Click += async (s, e) =>
{
int len = await GetLengthAsync();
txt03.Text = "Complete the work. result = " + len;
};
// 2. 非匿名函数方式
btn.Click += BtnClicked;
private async void BtnClicked(object sender, RoutedEventArgs e)
{
int len = await GetLengthAsync();
txt03.Text = "Complete the work. result = " + len;
}
- 异步方法返回
Task<string>
意味着在await
该Task时,将会返回一个string
内容。 - 在等待任务返回结果之前,程序可以做其它的不依赖于该任务结果的事情。
- 异步函数
GetLengthAsync()
的执行流程及await
关键字的注意事项:await
会让GetLengthAsync()
函数暂时挂起,以等待client.GetStringAsync()
返回结果,
在此之前GetLengthAsync()
函数不会继续向下执行。因此异步函数只在出现await
关键字的地方挂起等待。- 同时会将控制权交还给调用
GetLengthAsync()
的函数。 - 当
client.GetStringAsync()
函数执行结束,控制权将重新回到该处。 - 然后
await
操作符将从GetStrTask
中获取string
内容。
2. 有CPU性能限制的代码:需要使用await Task.Run
来在后台执行相应的操作,以保证不会阻塞主线程。
private async Task RunAsync()
{
await Task.Run(() =>
{
int sum = 0;
for (int i = 0; i < 100000000; ++i)
{
sum += i;
}
Console.WriteLine("The result is {0}", sum);
});
}
异步方法的总结
- 异步函数声明时需要包含
async
关键字 - 异步方法的命名通常后缀为 Async
- 其返回值一般有以下几种形式:
Task
:方法没有返回值。Task<T>
:返回值类型为T
void
: 异步事件处理方法- Lambda表达式时,不在此范围。
- 异步方法中通常包含至少一个
await
的表达式,表明在此处该函数将不再继续执行,直到await
处的异步操作结束为止。
在此期间,该函数被挂起,且控制权返回给调用者。await
关键字相当于告诉异步函数在此进行等候,等待await
后面的表达式执行结束后,异步函数再获得控制权并继续向下执行。 - 同步方法在运行结束之后直接返回,而异步方法在挂起时会返回一个
task
,当异步的方法最终结束之后,返回的task
会被标注完成,如果有返回值的话会被存储在task
中。 - 异步编程中调用的API,其后缀都是
Async
,表示异步方法,需要配合async
,await
来使用。 - 异步编程中控制权如何在方法之间进行流转,如下图所示:
参考资料:
Asynchronous programming
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?