c#进阶(7)—— 异步编程基础(async 和 await 关键字)

  async 和 await 关键字只是编译器功能,编译器会用Task类创建代码。

返 回值是一个Task,这种返回新线程的方法虽然可以提高系统的响应能力,但是多线程取值会给编码带来不便,所以新出的关键字await用于阻塞当前线程并 获取目标线程的返回值,在方法体中使用await关键字后要求将方法声明为async用来表示该方法是异步的,并且返回值必须为void或者将返回者封装 在一个Task中

1、创建任务

  同步方法Greeting ,该方法等待一段时间后,返回一个字符串,通过GetHashCode 查看当前线程ID

代码如下:

复制代码

        static string Greeting(string name){Task.Delay(3000).Wait();int j  = Task.CurrentId.GetHashCode();Console.WriteLine("name" + name);int i =Thread.CurrentThread.GetHashCode();Thread.Sleep(3000);Console.WriteLine("Task 的线程HASHCODE是: " + j);Console.WriteLine("Thread 的线程HASHCODE是" + i);Console.ReadLine();Thread.Sleep(3000);return $"Hello,{name}";}

复制代码

定义方法GreetingAsync,可以使方法异步化,基于任务的异步模式指定,在异步方法名后加上Async后缀,并返回一个任务,异步方法GreetingAsync 和 同步方法Greeting具有相同的输入参数,但是异步方法返回的是Task<string>,Task<string> 定义了一个返回字符串的任务。代码如下所示:

复制代码

        /// <summary>/// 异步调用方法/// </summary>/// <param name="name"></param>/// <returns></returns>static Task<string> GreetingAsync(string name){return Task.Run<string>(()=>{return Greeting(name);});}

复制代码

2、调用异步方法

可以使用await 关键字来调用返回任务的异步方法GreetingAsync,使用await 关键字需要用async修饰符声明的方法,在GreetingAsync方法完成前,该方法内其他代码不会继续执行,但是启动

CallerWithAsync方法的线程可以被重用,该线程没有阻塞。

代码如下所示:

复制代码

    class Program{static void Main(string[] args){CallerWithAsync();}/// <summary>/// 调用异步方法/// </summary>private async static void CallerWithAsync(){string result = await GreetingAsync("chenk");Console.WriteLine(result);}

复制代码

 3、延时任务

GreetingAsync 方法返回一个Task<string> 对象,对象包含任务创建的信息,并保存到任务完成,Task类的ContinueWith 方法定义了任何完成后就调用的代码,指派给ContinueWith方法的委托,将已完成的任务作为参数传入,使用Result属性,可以访问任务返回的结果。代码如下:

复制代码

        /// <summary>/// 延续任务/// </summary>private static void CallerWithContinuationTask(){Task<string> t1 = GreetingAsync("chenk");//编译器把await 关键字后的代码放进ContinueWith 方法的代码块转换await关键字t1.ContinueWith(t =>{string result = t.Result;Console.WriteLine("CallerWithContinuationTask 线程Id :" + Thread.CurrentThread.GetHashCode() + "; result 的值为:" +result);Console.ReadLine();});}

复制代码

4、同步上下文

验证方法中使用的线程,可以点击‘启动’——在‘调试’中选择‘线程’,即可查看当前异步程序运行的线程数及位置,以CallerWithContinuationTask为例,可以看到一个线程为主线程、一个线程在调用GreetingAsync方法、一个线程在执行ContinueWith方法内的代码堆。截图如下:

 

5、使用多个异步方法

5.1 按顺序调用多个异步方法

使用await 关键字可以调用每个异步方法,如果一个异步方法依赖于另一个异步方法的结果,await关键字就非常有用。

本例中,GreetingAsync 异步方法的第二次调用完全独立于第一次调用的结果,如果每个异步方法都不使用await,那么整个MultipleAsyncMethods异步方法将更快返回结果。代码如下:

复制代码

        private async static void MutipleAsyncMethods(){string s1 = await GreetingAsync("chenk");string s2 = await GreetingAsync("zhangf");Console.WriteLine("Finished both methods \nResult 1:" + s1 + "\nResult 2:" + s2);Console.ReadLine();}

复制代码

  5.2 使用组合器

如果异步方法不依赖于其他异步方法,则每个异步方法都不使用await ,而是把每个异步方法的返回结果赋值给Task变量,就会运行的更快,GreetingAsync方法返回Task<string>。这些方法现在可以并行执行了。

组合器可以帮助实现这一点,一个组合器可以接受多个同一类型的参数,并返回同一类型的值,多个同一类型的参数被组合成一个参数传递,Task组合器接受多个Task对象作为参数,并返回一个Task。

示例代码采用Task.WhenAll组合器方法,它可以等待,直到两个任务都完成。代码如下:

复制代码

        /// <summary>/// 组合器 WhenAll/// </summary>private async static void MultipleAsyncMethodWithCombinatoral(){Task<string> t1 = GreetingAsync("chenk");Task<string> t2 = GreetingAsync("zhangf");//WhenAll 组合器,从WhenAll方法返回的Task,是在所有传入方法的任务都完成了才会返回Task。//WhenAny 组合器,是在其中一个传入方法的任务完成了就会返回Task。await Task.WhenAll(t1, t2);}/// <summary>/// 组合器WhenAll 重载,如果所有的任务返回相同的类型,那么该类型的数组可用于await返回的结果/// </summary>private async static void MultipleAsyncMethodWithCombinatoral2(){Task<string> t1 = GreetingAsync("chenk");Task<string> t2 = GreetingAsync("zhangf");string[] result = await Task.WhenAll(t1, t2);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438351.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字节二面 —— 什么是同步锁、死锁、乐观锁、悲观锁

马上就要到金三银四佳季了&#xff0c;是找工作的好时候&#xff0c;小伙伴们一定要把握好时机&#xff0c;找到心仪的高薪工作。找工作就少不了面试&#xff0c;那我们从现在开始&#xff0c;多刷刷面试题&#xff0c;查缺补漏&#xff01;&#xff01;&#xff01; 目录 1. …

C#进阶之WebAPI(一)

最近出去面试&#xff0c;被问到关于WebAPI的知识&#xff0c;因为项目中没有单独写过WebAPI&#xff0c;使用的时候是和mvc结合在一起使用的&#xff0c;所以&#xff0c;在我的印象中WebAPI和mvc是差不多的&#xff0c;这种答案当然不能让人满意了&#xff0c;于是今天做个关…

【LeetCode-SQL每日一练】—— 620. 有趣的电影

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦。大家可以叫我小梦~ 小伙伴们都知道&#xff0c;不管是在学习中还是日常工作中&#xff0c;几乎天天是要跟数据库打交道的&#xff0c;为了更好的操作数据库&#xff0c;我们的SQL知识储备是必不可少的…

改了一行代码,MySQL查询效率提升了80%,老板奖了我50万

⭐前言 优化MySQL数据库是数据库管理员必备的技能&#xff0c;通过不同的优化方式方法来达到提高MySQL数据库性能的目的。 MySQL数据库当用户和数据量非常少的情况下&#xff0c;我们就很难判断MySQL数据库性能的好坏。只有当用户量与数据量大起来&#xff0c;MySQL的性能如何才…

C#进阶之WebAPI(二)

今天学习一下&#xff1a;WebAPI如何使用呢&#xff1f; 首先我们打开vs新建一个WebAPI项目&#xff0c;可以看到一共有这些文件夹目录 首先了解一下这些文件夹/文件的意义&#xff08;按照程序启动的流程&#xff0c;相关的配置项就不说了&#xff09;&#xff0c; Global.as…

字节一面 —— List 和 Map、Set 的区别

马上就要到金三银四佳季了&#xff0c;是找工作的好时候&#xff0c;小伙伴们一定要把握好时机&#xff0c;找到心仪的高薪工作。找工作就少不了面试&#xff0c;那我们从现在开始&#xff0c;多刷刷面试题&#xff0c;查缺补漏&#xff01;&#xff01;&#xff01; 目录 ⭐常…

C#进阶之WebAPI(三)

今天复习一下WebAPI的路由知识&#xff1a; 首先分析一下MVC路由和WebAPI路由的区别&#xff1a; 在mvc里&#xff0c;默认的路由机制是通过URL路径去匹配控制器和Action方法的&#xff0c;在mvc中的默认路由定义在App_Start文件夹下的RouteConfig.cs文件下&#xff1a; publ…

阿里一面 —— HTTP中重定向和请求转发的区别?

马上就要到金三银四佳季了&#xff0c;是找工作的好时候&#xff0c;小伙伴们一定要把握好时机&#xff0c;找到心仪的高薪工作。找工作就少不了面试&#xff0c;那我们从现在开始&#xff0c;多刷刷面试题&#xff0c;查缺补漏&#xff01;&#xff01;&#xff01; 目录 ⭐T…

C#异步编程-------异步编程模型(APM)

术语解释&#xff1a; APM 异步编程模型&#xff0c; Asynchronous Programming Model EAP 基于事件的异步编程模式&#xff0c; Event-based Asynchronous Pattern TAP 基于任务的异步编程模式&#xff0c; Task-based Asynch…

【LeetCode-SQL每日一练】—— 627. 变更性别

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦。大家可以叫我小梦~ 又到了练习SQL的时候啦&#xff01;一起来学习吧&#xff01; &#x1f64b;‍♂️ 小伙伴们如果在学习过程中有不明白的地方&#xff0c;欢迎评论区留言提问&#xff0c;小梦定知无…

iis运行原理 Asp.Net详解IIS内部运行原理

本章节主要讲IIS和 管道内部如何处理客户端Http请求&#xff0c;会较多的以代码的形式讲述&#xff0c;让大家对HttpApplication、HttpHandler、HttpApplicationFactory、Page这几个在处理请求过程中扮演重要角色的对象有更深入的了解。 下面我们通过单步调式跟踪System.Web.D…

【LeetCode-SQL每日一练】—— 1179. 重新格式化部门表

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦。大家可以叫我小梦~ 又到了练习SQL的时候啦&#xff01;一起来学习吧&#xff01; &#x1f64b;‍♂️ 小伙伴们如果在学习过程中有不明白的地方&#xff0c;欢迎评论区留言提问&#xff0c;小梦定知无…

阿里一面 —— 什么是多线程?

马上就要到金三银四佳季了&#xff0c;是找工作的好时候&#xff0c;小伙伴们一定要把握好时机&#xff0c;找到心仪的高薪工作。找工作就少不了面试&#xff0c;那我们从现在开始&#xff0c;多刷刷面试题&#xff0c;查缺补漏&#xff01;&#xff01;&#xff01; 目录 ⭐什…

第九节:JWT简介和以JS+WebApi为例基于JWT的安全校验

一. 简介 1. 背景 传统的基于Session的校验存在诸多问题&#xff0c;比如&#xff1a;Session过期、服务器开销过大、不能分布式部署、不适合前后端分离的项目。 传统的基于Token的校验需要存储Key-Value信息&#xff0c;存在Session或数据库中都有弊端&#xff0c;如果按照一…

赢在CSDN —— 我们一起向前

赢在CSDN&#xff0c;一起向前&#xff01; ⭐初遇CSDN ⭐我也成为了一名创作博主 ⭐如何在CSDN赚到一桶金 ⭐CSDN带给自己的成长 ⭐对CSDN的期待 ⭐个人创作的规划 ⭐初遇CSDN 不知不觉来到CSDN已经有1379天的时间啦&#xff0c;时间过得好快呀&#xff01;记得刚踏进CS…

volatile关键字的作用-适用场景

volatile在Java并发编程中常用于保持内存可见性和防止指令重排序。内存可见性&#xff08;Memory Visibility&#xff09;&#xff1a;所有线程都能看到共享内存的最新状态&#xff1b;防止指令重排&#xff1a;在基于偏序关系的Happens-Before内存模型中&#xff0c;指令重排技…

MySQL你掌握了多少?这些SQL题你能作对几道?

MySQL是工作中常用数据库&#xff0c;必须掌握&#xff0c;但小伙伴们又掌握了多少呢&#xff0c;今天一起来测试一下吧~ 力扣SQL ⭐组合两个表 ⭐第二高的薪水 ⭐超过经理收入的员工 ⭐查找重复的电子邮箱 ⭐从不订购的客户 ⭐大的国家 ⭐删除重复的电子邮箱 ⭐有趣的…

mybatis配置文件加注释报错怎么办?改一笔就能帮你解决

今天配置mybatis写了一个小demo&#xff0c;本以为顺顺利利的就完成了&#xff0c;没想到就报了如下错误。直接emo了。 java.lang.ExceptionInInitializerErrorat com.lm.learn.dao.UserTest.getUsers(UserTest.java:14)at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ…

第十二节:深究内核模式锁的使用场景(自动事件锁、手动事件锁、信号量、互斥锁、读写锁、动态锁)

一. 整体介绍 温馨提示&#xff1a;内核模式锁&#xff0c;在不到万不得已的情况下&#xff0c;不要使用它&#xff0c;因为代价太大了&#xff0c;有很多种替代方案。 内核模式锁包括&#xff1a; ①&#xff1a;事件锁 ②&#xff1a;信号量 ③&#xff1a;互斥锁 ④&#xf…

玩转Mybatis —— 一个小demo,带你快速入门Mybatis

目录 &#x1f91e;Mybatis官网介绍 &#x1f91e;Mybatis安装 &#x1f91e;Mybatis核心配置文件 &#x1f91e;构建 SqlSessionFactory &#x1f91e;获取 SqlSession &#x1f91e;通过 XML 定义已映射的 SQL 语句 &#x1f91e;作用域&#xff08;Scope&#xff09;…