.NET 中 async 和 await

前言

C# 中的 Async 和 Await 关键字是异步编程的核心。使用这两个关键字可以轻松创建异步方法。使用 async 关键字定义的异步方法简称“异步方法”。

异步编程

并发的一种形式,它采用furture模式或回调(callback)机制,以避免产生不必要的线程。.Net中future的类型有 TaskTask<Result>

异步编程的核心理念是异步操作:

启动了的操作将会在一段时间后完成。

这个操作正在执行时,但不会阻塞原来的线程。

启动了这个操作的线程后,可以继续执行其它任务。

当操作完成时,它会通知它的future,或者调用回调函数,以便让程序知道操作已经结束。

异步的好处

  1. 对于面向终端用户的GUI程序,异步可以提高响应能力。

  2. 对于服务器应用:异步编程实现了可扩展。

    服务器可以利用线程池填满其可扩展性,使用异步编程后,可扩展性通常可以提供一个数量级,可以最大程度的压榨服务器性能,提高处理能力。

async

使用 async 修饰符可以将方法、lambda表达式或匿名方法指定为异步。

async 的主要目的是,使方法内的await关键字生效。

//等待异步完成再执行后边的操作,但是整个方法不会阻塞
var result = await DoSomethingAsync();
output.Result = result;

如果使用了 Async 最好一直使用它

await

async 标记的异步方法,可以使用 await 来指定暂定点。await 运算符通知编译器异步方法:在等待的异步过程完成后才能继续通过该点。同时,会将控制权返回至异步方法的调用方

async 方法在开始时以同步的方式执行。在 async 方法内部,await 关键字对他的参数(一个异步任务)执行一个异步等待。它首先检查操作是否已经完成,如果完成了,就继续运行(同步方法)。否则,他会暂停 async 方法,并返回,将控制权交给调用方,留下一个 未完成的 Task。一段时间后,操作完成,async方法再恢复运行。

await 语句等待一个任务完成,当该方法在 await 处暂停时,就可以捕捉上下文(context)。如果当前SynchronizationContext不为空,这个上下文就是当前SynchronizationContext。如果当前SynchronizationContext为空,则这个上下文为当前TaskScheduler。该方法会在这个上下文中继续运行。

//此时await会捕获当前上下文
await DoSomethingAsync();
//....    //这里会试图用上边捕获的上下文继续执行
await DoSomethingAsync().ConfigureAwait(false);
//.... 这里开始在新的线程中运行

ConfigureAwait 配置 Taskawaiter,将延续任务封装回原始上下文,则为True ,否则为 False

详情可查阅ConfigureAwait(false)资料,这里暂时不做赘述。可阅读以下文章

  • 原文ConfigureAwait FAQ  

    https://devblogs.microsoft.com/dotnet/configureawait-faq/

  • 译文理解C#中的ConfigureAwait

    https://www.cnblogs.com/xiaoxiaotank/p/13529413.html

异步方法异常:

异步方法异常时会返回在 Task 对象中,并将这个 Task 对象的状态改变为“已完成”。当 await 调用该 Task 对象时,await 会获得并(重新)抛出该异常,并保留原始的栈轨迹。

注意:

异步方法避免使用 Task.WaitTask<T>.Result ,因为他们会导致死锁。

示例:

public async Task<int> GetUrlContentLengthAsync()
{var client = new HttpClient();//异步执行请求,立即返回一个Task<string>,并将控制权让出Task<string> getStringTask =client.GetStringAsync("https://docs.microsoft.com/dotnet");//由于异步方法未执行等待,所以可以继续执行不依赖异步返回结果的同步方法DoIndependentWork();//挂起任务进度,并将控制权交割GetUrlContentLengthAsync方法的调用方,并返回一个Task<int>给调用方。//该任务表示将返回下载字符串长度的一个承诺//然后调用方会继续执行,执行不依赖于GetUrlContentLengthAsync返回结果的其它工作,否则就等待。string contents = await getStringTask;return contents.Length;
}void DoIndependentWork()
{Console.WriteLine("Working...");
}

await 运算符会暂停 GetUrlContentLengthAsync 方法:

  • getStringTask 完成之前,GetUrlContentLengthAsync 无法继续。

  • 同时,控件返回至 GetUrlContentLengthAsync 的调用方。

  • getStringTask 完成时,控件将在此继续。

  • 然后,await 会从 getStringTask 检索 string 结果

如果 DoIndependentWork 依赖于异步执行的结果,则在等待 getStringTask 返回结果期间不能进行任何工作。需要改成以下写法。

string getStringTask = await client.GetStringAsync("https://docs.microsoft.com/dotnet");

构成异步方法的条件:

  1. 方法签名要包含 async 修饰符。

  2. 按照约定,异步方法的名称以“Async”后缀结尾。

  3. 返回类型为以下类型之一

    1. 如果你的方法有返回值,则返回 Task<Result> 的类型。

    2. 如果你的方法没有返回值,则返回 Task 类型

  4. 方法中至少要包含一个 await 表达式,该表达式标记一个点,在该点上,直到等待的异步操作完成方法才能继续。同时,并且将控制权返回到方法的调用方。

返回类型

await 运算符的操作数通常是以下几种.NET类型:Task、Task<TResult>、ValueTask或VauleTask<TResult>。但是任何可等待表达式都可以是await运算符的操作数。

总结

  1. 异步可以提高响应能力。

  2. 异步不会阻塞线程

  3. 使用 async 来标记异步方法

  4. 使用 await 来指定暂停点,挂起其进度,在等待的异步过程完成后才能继续通过该点。同时,会将控制权返回至异步方法的调用方,调用方可以继续执行不依赖于异步返回结果的其它工作。

  5. 如果使用了 Async 最好一直使用它

  6. 异步方法避免使用 Task.WaitTask<T>.Result ,因为他们会导致死锁。

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

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

相关文章

Javascript 常用技巧 [2]

Javascript 常用技巧 [2] /**请问如何去掉主页右面的滚动条&#xff1f; <!-- <body scroll"no"> --> <!-- <body style"overflow-y:hidden"> --> ******************************** 怎样不使用页面的缓存&#xff1f;即每一次打…

mongodb可视化工具 linux,Linux中安装启动MongoDB与可视化工具

MongoDB 提供了 linux 各发行版本 64 位的安装包&#xff0c;你可以在官网下载安装包。下载地址&#xff1a;https://www.mongodb.com/download-center#community下载完安装包&#xff0c;并解压 tgz(以下演示的是 64 位 Linux上的安装) 。curl -O https://fastdl.mongodb.org/…

年轻有为的老黄2020

0x01 不知道开篇要说什么好&#xff0c;那就来个经典的 0x01 吧。这个世界不止苟且&#xff0c;还有诗和远方。工作 工作上面还算是比较忙碌的&#xff0c;在20年也做了很多东西&#xff0c;本来面试进公司的时候title是高开&#xff0c;在基础架构组&#xff0c;光杆部门。过完…

VS.NET调试问题

Q:VS.NET调试问题 A:关于VisualStudio.NET里调试出现的一系列问题&#xff0c;例如没有权限调试Web服务器&#xff0c;不属于Debugger Users组、无法调试等情况&#xff0c;都可以在The VS7 Debugger doesn’t work. What can I do(http://blogs.msdn.co…

linux调用odbc接口乱码,linux中pypyodbc读取GB编码mdb中文乱码解决办法

当前1.3.3版本的pypyodbc在linux系统上面已经可以读取有中文字符的mdb文件,不再出现异常,但是读取的中文字符却全是乱码。下面是根据一些现象的合理推论:mdb文件来自于windows系统,其中的中文字符使用GB编码无疑,但linux系统上mdbtools提供的odbc驱动底层已经执行了编码转换,将…

推荐:Dapper扩展-Dapper.SimpleCRUD

背景Dapper目前应该是大家比较喜欢的orm框架之一&#xff0c;但是它灵活的背后&#xff0c;还是有很多不尽人意的地方&#xff0c;谁想编写基本的读取/插入/更新/删除语句&#xff1f;下面推荐SimpleCRUD为Dapper提供了简单的CRUD帮助器。解放了大家&#xff0c;提高生产力。功…

创建虚拟磁盘的小工具软件plainmaker.exe

此小工具,在虚拟机中做集群实现时用到!其下载地址如下:[url]http://www.vmware.cn/Soft/69.html[/url]

Linux下的MySQL测试,Linux下MySQL命令(1)

启动命令&#xff1a;$ ./mysqld_safe --defaults-file/home/mysql/local/mysql_sale_mirror/etc/my.cnf --basedir/home/mysql/local/mysql_sale_mirror/ --datadir/home/mysql/local/mysql_sale_mirror/var/ --pid-file/home/mysql/local/mysql_sale_mirror/var/mysql.pid --…

深入浅出Dotnet Core的项目结构变化

有时候&#xff0c;越是基础的东西&#xff0c;越是有人不明白。前几天Review一个项目的代码&#xff0c;发现非常基础的内容&#xff0c;也会有人理解出错。今天&#xff0c;就着这个点&#xff0c;写一下Dotnet Core的主要类型的项目结构&#xff0c;以及之间的转换和演化。一…

群策群力:破机房征求灵丹妙药

我校有一年代久远之计算机教室&#xff0c;现已经迈入日落西山之境。特征求灵丹妙药&#xff0c;不求妙手回春&#xff0c;只愿其能为我校的信息技术教育事业再尽最后一把微力&#xff0c;也为我校即将面临无地授课的教师提供继续上岗的救命稻草一枝。具体情况说明&#xff1a;…

使用 C# 9 的records作为强类型ID - 路由和查询参数

上一篇文章&#xff0c;我介绍了使用 C# 9 的record类型作为强类型id&#xff0c;非常简洁public record ProductId(int Value);但是在强类型id真正可用之前&#xff0c;还有一些问题需要解决&#xff0c;比如&#xff0c;ASP.NET Core并不知道如何在路由参数或查询字符串参数中…

linux sudo 必须属于用户ID0,sudo:/usr/bin/sudo 务必属于用户 ID 0(的用户)并且设置 setuid 位...

今天手抖本来要修改/usr/bin/下面的一个文件属性为 user:user&#xff0c;执行chown -R /usr/bin/的时候&#xff0c;再按tab之前直接敲了回车&#xff1b;结果导致执行sudo命令时出现错误提示&#xff1a;“sudo&#xff1a;/usr/bin/sudo 必须属于用户 ID 0(的用户)并且设置…

企业形象广告的几个突破要点

企业形象广告的使用不能简单的说好与不好&#xff0c;特定的企业&#xff0c;特定的行业&#xff0c;有不同的功能和效果&#xff0c;一般大众化消费品较为适宜&#xff0c;但也要注意&#xff1a; 1、 如果一个企业的产品处于一个完全成熟的品牌阶段&#xff0c;不易投入大量的…

公司高层要我转Java 我直接邮件回怼...

2020年艰难而短暂&#xff0c;而互联网的历史车轮还是轰隆隆一路向前&#xff0c;服务网格/云原生/Serverless架构&#xff0c;各种新架构大行其道。重新审视当下主流的编程语言&#xff0c;天下第一的Java已老&#xff0c;下行多年的.NET却浴火重生&#xff0c;焕发生机&#…

linux如何实现网络高级编程,嵌入式Linux网络编程之:网络高级编程-嵌入式系统-与非网...

10.3 网络高级编程在实际情况中&#xff0c;人们往往遇到多个客户端连接服务器端的情况。由于之前介绍的如connet()、recv()和send()等都是阻塞性函数&#xff0c;如果资源没有准备好&#xff0c;则调用该函数的进程将进入睡眠状态&#xff0c;这样就无法处理I/O多路复用的情况…

.NET斗鱼直播弹幕客户端(2021)

.NET斗鱼直播弹幕客户端(2021)离之前更新的两篇《.NET斗鱼直播弹幕客户端》已经有一段时间&#xff0c;近期有许多客户向我反馈刚好有这方面的需求&#xff0c;但之前的代码不能用了——但网上许多流传的Node.js、Python脚本却可以用&#xff0c;这岂能忍&#xff1f;&#xff…

McAfee推免费版SiteAdvisor安全上网工具

McAfee近期宣布推出完全免费版McAfee SiteAdvisor上网工具。McAfee SiteAdvisor是业界第一款Web安全工具&#xff0c;能够主动地提醒用户在浏览、搜索和即时通信或收发电子邮件时所遇到的危险站点&#xff0c;避免遭到网络钓鱼、间谍软件等恶意程序的***。 McAfee SiteAdvisor是…

9050 端口 linux 进程,windows和linux查看端口占用情况

一、Windows平台在windows命令行窗口下执行&#xff1a;1.查看所有的端口占用情况C:\>netstat -ano协议 本地地址 外部地址 状态 PIDTCP 127.0.0.1:1434 0.0.0.0:0 LISTENING 3236TC…

Exceptionless服务端本地化部署

背景分布式异常日志收集框架Exceptionless是开源的工具&#xff0c;根据官方给出的说明&#xff1a;Exceptionless提供两种使用方式&#xff0c;一种是官网创建账号,需要付费&#xff0c;免费版有限制&#xff1b;一种是自己搭建本地项目&#xff0c;无任何限制。准备安装包准备…

微软所谓的无人工介入的自动的机器翻译系统

近日在微软网站上查找资料,发现一个资料里有如下的声明性描述:注意&#xff1a;这篇文章是由无人工介入的自动的机器翻译系统翻译完成。这些文章是微软为不懂英语的用户提供的, 以使他们能够理解这些文章的内容。微软不保证机器翻译的正确度&#xff0c;也不对由于内容的误译或…