C# async / await 的使用方法
创始人
2024-01-25 18:36:04
0

目录

一、简介

二、异步等待返回结果

三、异步方法的返回类型

四、await foreach

五、Task.Delay

结束


一、简介

await 运算符暂停对其所属的 async 方法的求值,直到其操作数表示的异步操作完成。 异步操作完成后,await 运算符将返回操作的结果(如果有)。 当 await 运算符应用到表示已完成操作的操作数时,它将立即返回操作的结果,而不会暂停其所属的方法。 await 运算符不会阻止计算异步方法的线程。 当 await 运算符暂停其所属的异步方法时,控件将返回到方法的调用方。

二、异步等待返回结果

下面就演示 await 运算符常用的一些用法。

新建一个基于 .Net6 的 Winform 项目,界面就两个按钮,如下:

代码 

namespace 异步编程
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){IsTrue = false;AwaitEnd();}private void button2_Click(object sender, EventArgs e){IsTrue = true;}private bool IsTrue = false; private Task StartTimer(){var t = Task.Run(() =>{while (true){if (IsTrue)return "555";Thread.Sleep(100);}});return t;}private async void AwaitEnd(){Console.WriteLine("开始执行,时间:" + DateTime.Now.ToString());var res = await StartTimer();Console.WriteLine("结束:" + res + " 时间:" + DateTime.Now.ToString());}}
}

点击按钮1开始启动异步,点击按钮2,就返回结果,如果不点击按钮2,那么 while 循环就不会停止。

效果:

可以看到,点击了按钮1后,并不会让主线程卡死,窗体还是可以随意的拖动的,直到 StartTimer 方法将返回值返回回来后,才会继续执行后续的代码,这对一些需要阻塞线程,并获取另外的计算结果,然后才能继续计算的需求而言,有极大的帮助,比如读取数据库数据,如果网速比较慢,并且不会立刻就返回结果,用 await 运算符就可以在同一个方法里,等到获取到数据库返回结果后,再进行下一步运算,而不是从上到下,一下子就执行完了。

下面是以前我查询数据库写的代码,效果和上面演示中的 await 运算符是一样的,在下面的方法中,使用 Action 回调,代码都没写到一起,虽然逻辑一样,但用起来就不是那么的方便。

/// 
/// 执行SQL语句,并获取值
/// 
/// 
/// 
private static void ExecuteAndReturnValue(string sql, Action callBack)
{Func Funcs = () =>{DataSet dataSet = MySqlHelper.GetDataSet(sql);if (dataSet == null || dataSet.Tables.Count == 0)return null;return dataSet.Tables[0];};//执行任务Task printRes = Task.Run(Funcs);//等待任务完成printRes.GetAwaiter().OnCompleted(() =>{if (callBack != null)callBack(printRes.Result);});
}

当前的示例,只是执行单个任务,如果有多个任务,用下面的方法也是可以的,

private Task DoSomethingAsync(int x)
{return Task.Run(() =>{Thread.Sleep(1000);Console.WriteLine("值:" + x);});
}public async Task RunAsync()
{foreach (var x in new[] { 1, 2, 3 }){await DoSomethingAsync(x);}
}

DoSomethingAsync 方法中,返回值可以从另一个数组中获取到 Task 并执行,我这里就不写那么仔细了,如果用面向过程的写法,就是这么写的:


private async void Test()
{await Task.Run(async () =>{await Task.Delay(4000);Trace.WriteLine("第1个线程执行");});await Task.Run(async () =>{await Task.Delay(3000);Trace.WriteLine("第2个线程执行");});await Task.Run(async () =>{await Task.Delay(2000);Trace.WriteLine("第3个线程执行");});
}

三、异步方法的返回类型

在方法里加上了 async 关键字后,返回值就只能使用固定的几个了,不然会报错。

异步函数的返回类型只能为: void、Task、Task、ValueTask 或 ValueTask

Task: 代表一个返回值T类型的操作。

Task: 代表一个无返回值的操作。

void: 为了和传统的事件处理程序兼容而设计。

四、await foreach

可以使用 await foreach 语句来使用异步数据流,即实现 IAsyncEnumerable 接口的集合类型。 异步检索下一个元素时,可能会挂起循环的每次迭代。

代码

private async void Test()
{IAsyncEnumerable pullBasedAsyncSequence = ProduceAsyncSumSeqeunc(5);//开始另一项任务;用于使用异步数据序列!var consumingTask = Task.Run(() => ConsumeAsyncSumSeqeunc(pullBasedAsyncSequence));await Task.Delay(TimeSpan.FromSeconds(3));Console.WriteLine("搞一些其他事");//只是为了演示!等待任务完成!await consumingTask;Console.WriteLine("异步流演示完成!" );
}private async Task ConsumeAsyncSumSeqeunc(IAsyncEnumerable sequence)
{Console.WriteLine("执行 ConsumeAsyncSumSeqeunc 方法");await foreach (var value in sequence){Console.WriteLine($"value: {value}");await Task.Delay(TimeSpan.FromSeconds(1));};
}private async IAsyncEnumerable ProduceAsyncSumSeqeunc(int count)
{Console.WriteLine("执行 ProduceAsyncSumSeqeunc 方法");int index = 0;for (int i = 0; i < count; i++){await Task.Delay(TimeSpan.FromSeconds(0.5));yield return index += count;}
}

调用 Test 方法后,即可打印

五、Task.Delay

解释:创建将在时间延迟后完成的任务。命名空间: System.Threading.Tasks

在上面的演示中用到了多次,例:

await Task.Delay(TimeSpan.FromSeconds(0.5));

在 Delay 方法中,可以用 TimeSpan 中的时、分、秒 表示

参考:

Delay(Int32)

创建一个在指定的毫秒数后完成的任务。

Delay(TimeSpan)

创建一个在指定的时间间隔后完成的任务。

Delay(Int32, CancellationToken)

创建一个在指定的毫秒数后完成的可取消任务。

Delay(TimeSpan, CancellationToken)

创建一个在指定的时间间隔后完成的可取消任务。

结束

如果这个帖子对你有所帮助,欢迎 关注 、点赞 、留言

end

相关内容

热门资讯

泡泡火锅加盟费用 泡泡火锅加盟... 1、时尚风格潮流()泡泡一人一锅的精致分餐原则、时尚的吧台式就餐形式、自由简便的搭配吃法,食尚品牌的...
「泡泡火锅加盟泡泡火锅加盟费多... 泡泡世纪国际餐饮管理(北京)有限公司成立于2008年,位于北京市丰台区总部基地,毗邻多家500强企业...
宁波镇海px项目镇海px项目引... 10月24日,浙江省宁波市镇海区人民政府办公室网络发言人发布《关于镇海炼化一体化项目有关情况的说明》...
宁波镇海px项目群众聚集事件舆... 六、媒体评论摘要一些地方对重化工项目的抗拒,一方面表现了谁都不愿意为社会公共利益承担风险,另一方面也...
怡宝矿泉水加盟 怡宝矿泉水加盟... 小编点评:怡宝矿泉水口感甘甜清冽,爽口解渴,携带方便,深受广大消费者的青睐。利用优质水源,先进的科学...
怡宝矿泉水加盟 怡宝矿泉水加盟... 怡宝矿泉水属于华润集团。华润集团专业化利润中心锐意发展,锐意进取。一批企业已发展成为行业龙头企业。其...
空气能空调加盟 空气能空调加盟... 加盟介绍 太阳能光热企业日出东方·四季沐歌可实现年产30万台空气能热水器的广东顺德工业园首批产品下线...
李传荣重点项目建设深入调研重点... 张家界市委常委、市委组织部部长李传荣调研重点工程项目建设座谈会现场。红网时刻张家界5月21日讯(通讯...
国内常见的短信群发平台有短信群... 目前国内提供短信群发的平台正规的有证的主要有三大基础运营商(联通、电信、移动)、工信部批准的第三方短...
专利代理人资格考试怎么准备? ... 我参加的是19年考试,整个备考大概花了三个月,因为还有不少别的事,弄得兵荒马乱的。好在最后过了。分数...