C# 异步编程(async&await)

时间:2022-06-28 02:36:05

什么是异步编程

每次启动程序时,系统会自动在内存中创建一个进程。进程是构成运行程序的资源的集合。这些资源包括虚地址空间、文件句柄和许多其他程序运行所需的资源。
在进程的内部,系统会创建一个称为线程的内核(Kerne )的对象,它代表了真正的运行程序。线程是执行线程的简称。当进程建立,系统就会由主程序的Main方法的第一行语句处开始了线程的执行。

  • 在默认情况下,一个进程只包含一个线程,即从程序的开始,一直执行到结束。
  • 其实线程是可以派生其他线程,在任意时刻,一个进程都可以包含不同状态的多个线程,来执行程序的不同部分。
  • 如果一个进程拥有一个线程,它们将共享进程的资源。
  • 系统为处理器规划的执行单元,是线程而非进程。

在很多时候,我们在进程中使用单一线程从头到尾地执行程序,这种简单模式会导致性能和用户体验另人难以接受。
比如程序向另外一台服务器发出请求,由于网络等外部原因,此种通信任务往往会耗费大量时间,进程如果在此期间仅仅只能等待网络或网络上其他机器的响应,将严重地降低了性能。程序不应该浪费等待的时间,而应该更加高效地利用,在等待的时间执行其他任务,回复到达后在继续执行第一个任务。
如果程序调用某个方法,等待其执行全部处理后才能继续执行,我们称其为同步的。相反,在处理完成之前就返回调用方法则是异步的。
我们在编程语言的流程中添加了异步控制的部分,这部分的编程可以称之为异步编程

总结:

同步~同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去

异步~异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
     异步是一种目的。手段有 异步委托、多线程、线程池等...

.NET异步编程的发展历程

异步编程四个发展过程,参考:[你必须知道的异步编程]

NET1.1 APM(异步编程模型)

NET2.0 EAP(基于事件的异步编程模型)

NET4.0 TAP(基于任务的异步编程模型)

NET4.5 异步和等待(async和await)

但它们的本质都是使用线程池和委托机制的。

async/await模式之基本操作

在语法上,异步方法具有如下的特点:

  • 方法头中包含async方法修饰符。
  • 包含一个或多个await表达式,表示可以异步完成的任务。
  • 必须具备以下三种返回类型:
    • void
    • Task
    • Task<T>
  • 异步方法的参数可以为任意类型任意数量,但不能为out和ref参数。
  • 安装预定,异步方法的名称应该以Async为后缀。
  • 除了方法以外,Lambda表达式和匿名方法也可以作为异步对象。

异步方法的返回类型

  • Task<T>:如果调用方法要从调用中获取一个T类型的值,异步方法的返回值就必须是Task<T>。调用方法将通过读取Task的Result属性来获取这个T类型的值
Task<int> value = DoStuff.CalculateSumAsync(, );
...
Console.WriteLine( “Value: {}”, value.Result);

任何返回Task<T>类型的异步方法其返回值必须为T类型或可以隐式转换为T的类型。

  • Task:如果调用方法不需要从异步方法在返回值,但需要坚持异步方法的状态,那么异步方法可以返回一个Task类型的对象。这时,即使异步方法中出现return语句,也将不会返回任何东西
  • void:如果调用方法仅仅想执行异步方法,而不需要与它做进一步的交互时【这称为“调用并遗忘”(fire and forget)】,异步方法可以返回void类型。这时与上一种情况类似,即使异步方法中包含任何return语句,也不会返回任何东西。

学习参考:

1、探索c#之Async、Await剖析

使用Async标记Test为异步方法,用Await标记的方法 一般是需要耗时的操作。主线程碰到await时会立即返回,继续以非阻塞形式执行主线程下面的逻辑。当await耗时操作完成时,继续执行await后面的逻辑:

 Test();
Console.WriteLine("A逻辑");
static async void Test()
{
await Task.Run(() => { Thread.Sleep(1000); Console.WriteLine("B逻辑"); });
Console.WriteLine("C逻辑");
}

Async、Await的加入让原先这种混乱的步骤,重新拨正了,执行步骤是:A逻辑->B逻辑->C逻辑。

主线程调用Test(),await可能会开辟一个Task任务线程。

注意:这3个步骤是有可能会使用同一个线程的,也可能会使用2个,甚至3个线程。 可以用Thread.CurrentThread.ManagedThreadId测试下得知。

关于async和await常问的问题

问题一:是不是写了async关键字的方法就代表该方法是异步方法,不会堵塞线程呢?

  答: 不是的,对于只标识async关键字的(指在方法内没有出现await关键字)的方法,调用线程会把该方法当成同步方法一样执行,所以然而会堵塞GUI线程,只有当async和await关键字同时出现,该方法才被转换为异步方法处理。

问题二:“async”关键字会导致调用方法用线程池线程运行吗?

  答: 不会。被async关键字标识的方法不会影响方法是同步还是异步运行并完成,而是,它使方法可被分割成多个片段,其中一些片段可能异步运行,这样这个方法可能异步完成。这些片段界限就出现在方法内部显示使用”await”关键字的位置处。所以,如果在标记了”async”的方法中没有显示使用”await”,那么该方法只有一个片段,并且将以同步方式运行并完成。在await关键字出现的前面部分代码和后面部分代码都是同步执行的(即在调用线程上执行的,也就是GUI线程,所以不存在跨线程访问控件的问题),await关键处的代码片段是在线程池线程上执行。总结为——使用async和await关键字实现的异步方法,此时的异步方法被分成了多个代码片段去执行的,而不是像之前的异步编程模型(APM)和EAP那样,使用线程池线程去执行一整个方法。

其他学习

C#语法——await与async的正确打开方式

async & await 的前世今生(Updated)

关于async与await的FAQ

C#中 Thread,Task,Async/Await,IAsyncResult 的那些事儿!

异步编程系列

C# 异步编程(async&await)的更多相关文章

  1. 异步编程Async&sol;await关键字

    异步编程Async \await 关键字在各编程语言中的发展(出现)纪实. 时间 语言版本 2012.08.15 C#5.0(VS2012) 2015.09.13 Python 3.5 2016.03 ...

  2. 抓住异步编程async&sol;await语法糖的牛鼻子&colon; SynchronizationContext

    长话短说,本文带大家抓住异步编程async/await语法糖的牛鼻子: SynchronizationContext 引言 C#异步编程语法糖async/await,使开发者很容易就能编写异步代码. ...

  3. 温故知新,CSharp遇见异步编程&lpar;Async&sol;Await&rpar;,聊聊异步编程最佳做法

    什么是异步编程(Async/Await) Async/Await本质上是通过编译器实现的语法糖,它让我们能够轻松的写出简洁.易懂.易维护的异步代码. Async/Await是C# 5引入的关键字,用以 ...

  4. javascript异步编程 Async&sol;await

    Async/await Async/await 在学习他之前应当补充一定的 promise 知识 它是一种与 promise 相配合的特殊语法,目前被认为是异步编程的终级解决方案 值得我们每一个人学习 ...

  5. &lbrack;C&num;&rsqb; 谈谈异步编程async await

    为什么需要异步,异步对可能起阻止作用的活动(例如,应用程序访问 Web 时)至关重要. 对 Web 资源的访问有时很慢或会延迟. 如果此类活动在同步过程中受阻,则整个应用程序必须等待. 在异步过程中, ...

  6. &period;net 异步编程async &amp&semi; await关键字的思考

    C# 5.0引入了两个关键字 async和await,这两个关键字在很大程度上帮助我们简化了异步编程的实现代码,而且TPL中的task与async和await有很大的关系 思考了一下异步编程中的asy ...

  7. 异步编程async&sol;await

    什么是异步? 在异步程序中,程序代码不需要按照编写时的顺序严格执行,有时需要一在一个新的线程中运行一部分代码,有时无需创建新的 线程,但是为了更好的利用单个线程的能力,需要改变代码的执行顺序. 进程 ...

  8. c&num;异步编程async await

    可以代替协程了 但是需要.net4 版本 unity2017以上版本可以用了 再也可以不用蛋疼的没有返回值的协程了 //异步编程,和Task一起用 async void TestAsync(){ // ...

  9. &period;NetCore 异步编程 - async&sol;await

    前言: 这段时间开始用.netcore做公司项目,发现前辈搭的框架通篇运用了异步编程方式,也就是async/await方式,作为一个刚接触的小白,自然不太明白其中原理,最重要的是,这个玩意如果不明白基 ...

  10. &period;net 温故知新:【5】异步编程 async await

    1.异步编程 异步编程是一项关键技术,可以直接处理多个核心上的阻塞 I/O 和并发操作. 通过 C#.Visual Basic 和 F# 中易于使用的语言级异步编程模型,.NET 可为应用和服务提供使 ...

随机推荐

  1. Angular内置指令(一)

    要注意的是不要把自己开发的指令以ng开头,以免与内置指令冲突  目录:ng-disabled,ng-readonly,ng-checked,ng-selected,ng-href,ng-src,ng- ...

  2. SVN 之 去掉SVN管理标记

    当项目不需要SVN标志的时候, 方式一:很多人设置Windows显示隐藏文件,然后将项目中的所有.svn文件删除,这种方法是最笨的方法. 方式二:通过注册表方式 [1]新建一个文本文件.文本的内容为: ...

  3. 算法导论(第三版)Exercises4&period;2&lpar;第四章二节)

    4.2-1(计算结果) 18  14 62  66 4.2-2(Strassen算法计算矩阵乘法) void multiplyMatrix(int a[], int b[], int n, int r ...

  4. Factorization Machines 学习笔记(四)学习算法

      近期学习了一种叫做 Factorization Machines(简称 FM)的算法.它可对随意的实值向量进行预測.其主要长处包含: 1) 可用于高度稀疏数据场景:2) 具有线性的计算复杂度.本文 ...

  5. clone&lpar;&rpar;方法、深复制和浅复制

    clone方法 Java中没有明确提供指针的概念和用法,而实质上没个new语句返回的都是一个指针的引用,只不过在大部分情况下开发人员不需要关心如何去操作这个指针而已. 在实际编程中,经常会遇到从某个已 ...

  6. 如何部署Java&lowbar;web项目到云服务器上

    步骤 1:购买 Linux 实例(略) 步骤2:安装JDK 本节介绍如何安装java jdk. 软件包中包含的软件及版本如下: Tomcat:1.8.0_121 说明:这是写文档时参考的软件版本.您下 ...

  7. 理解npm run

    引言 ReactNative 开发中经常用到一些npm run的命令来打包.最近在这上面踩了一个坑,所以研究了一下. 在阅文做了两个ReactNative混合开发的项目,都用npm run bundl ...

  8. (原创)PouchDB 图片本地存储(web离线应用)

    /* * 参数 * db: 已建或未建数据库 * pouchId: 数据库唯一的主键_id * src: 图片img的DOM对象 * bg: 判断是否是背景图 * */ function addTod ...

  9. SSO系统的实现

    当一个网站系统比较大型的时候,我们通常采用面向服务的编程,采用分布式的编程.各个子系统共同来实现一个大的系统,这时候登录注册功能的实现也面临着一些问题. 一.WHAT? SSO是什么? sso是单点登 ...

  10. &equals;default&lpar;c&plus;&plus;11&rpar;

    1.概念 1)如果我们需要编译器默认的行为,则可以在参数列表后面加上=default来显式地要求编译器生成合成版本的默认构造函数和拷贝控制成员:合成的默认构造函数.合成拷贝构造函数.合成拷贝赋值运算符 ...