[c#语言]异步编程

一、什么是异步编程

        对于异步编程这一概念,可以用餐厅点餐为例。餐厅点餐的同时服务员在身旁等待称之为“同步点餐”。而自己点餐的同时服务员去照顾其他客人,等自己点完后再喊服务员则是“异步点餐”。

异步点餐

        优点:可以提高服务器接待请求的数量

        缺点:不会使单个请求的处理效率变高,甚至可能略有降低

 二、学会使用await、async

用async关键字修饰方法后,这个方法就成为了异步方法,但要注意以下几点:

        (1)异步方法的返回值一般是Task<T>泛型类型

        (2)按照约定,异步方法以Async结尾,虽不是语法强制,但是能让开发人员一眼看出是异步方法

        (3)如果方法没有返回值最好也声明为非泛型的Task类型,不建议使用void

        (4)调用泛型方法的时候,一般在方法前面加await关键字,这样方法调用的返回值就是泛型指定的T类型的值

        (5)一个方法如果有await调用,该方法也应修饰为async

代码演示如下:

Console.WriteLine("写入文件前");
await File.WriteAllTextAsync("D:/桌面文件/c#/csdn博客/1.txt","hello async");
Console.WriteLine("读取文件前");
string s = await File.ReadAllTextAsync("D:/桌面文件/c#/csdn博客/1.txt");
Console.WriteLine(s);

 await关键字的意思:调用异步方法,等异步方法结束后再继续向下执行。同时await可以直接把返回数据直接从<Task>中提取出来

         其实只要方法返回值是Task或者Task<T>类型,我们就可以用await关键字进行调用。对于调用者而言,被调用方法是否被修饰为async没有区别。修饰为async只是为了在方法内使用await调用。

 提醒:c# 9.0中新增了顶级语句允许直接在入口代码使用await关键字,如果不使用顶级语   句,需要用async修饰Main方法,然后把返回值修改为Task类型。

 2.1async、await原理深度解析

        结论:编译器会把async方法编译成一个大类,并且把异步方法的代码切分成多次方法调用。

验证如下:

         Thread.CurrentThread.ManagedThreadId用于获取当前线程ID,从上可以很清晰的看出前面三个线程都不同,但是第四个用同步进行调用的时候线程是相同的。

结论: 异步方法在进行await调用的等待期间,框架会把当前线程返回线程池,等异步方法调用执行完毕后,框架会从线程池再取出一个线程,以执行后续的代码。

 2.2异步方法不等于多线程

        很多人可能认为异步方法中的代码一定是在新线程中执行,所以和多线程划上等号。其实异步方法中的代码并不会自动在新线程执行,除非把代码放在新线程中执行。

验证如下:

       结论:异步方法代码不会自动在新线程中执行

         可以把要执行的代码以委托的形式传递给Task.Run,这样就从线程池中取出一个线程执行我们的代码。

 三、异步编程的几个重要问题

        (1).NET Core的类库已经全面拥抱异步了,但是有些类为了兼容旧API,也提供了非异步方法。建议只使用异步方法。

        (2)如果由于框架问题,方法无法标注为async,那么就无法使用await调用异步方法。对于返回值是Task<T>可以调用Result属性或者GetAwaiter().GetResult来等待异步结束执行获取返回值;对于返回值是Task类型可以在Task对象上调用wait方法调用异步方法并等待任务执行结束。(非特殊情况不建议使用,会阻塞线程的调用)

string s1 = File.ReadAllTextAsync("D:/桌面文件/c#/csdn博客/1.txt").Result;
string s2 = File.ReadAllTextAsync("D:/桌面文件/c#/csdn博客/1.txt").GetAwaiter().GetResult();
File.WriteAllTextAsync("D:/桌面文件/c#/csdn博客/1.txt", "hello").Wait();

        (3)异步暂停方法。如果需要异步方法暂停一段时间再执行,使用await Task.Delay();

        (4)使用CancellationToken类型的对象可以让异步方法提前终止。

        (5)可以使用Task.WhenAll同时等待多个Task的执行结束。Task.WhenAny方法用于等待多个任务,只要其中一个任务完成,代码就会继续向下执行。

Task<string> t1 = File.ReadAllTextAsync("D:/桌面文件/c#/csdn博客/1.txt");
Task<string> t2 = File.ReadAllTextAsync("D:/桌面文件/c#/csdn博客/2.txt");
Task<string> t3 = File.ReadAllTextAsync("D:/桌面文件/c#/csdn博客/3.txt");
string[] results = await Task.WhenAll(t1,t2, t3);
string s1 = results[0];
string s2 = results[1];
string s3 = results[2];

        (6)接口或者抽象类方法不能修饰为async,但是返回值可以设置为Task类型,在实现类中再根据需要为方法添加async进行修饰。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.net开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值