最近看了一些园友们写的有关于异步的文章,受益匪浅,写这篇文章的目的是想把自己之前看到的文章做一个总结,同时也希望通过更加通俗易懂的语言让大家了解"异步"编程。

1:什么是异步

  应用程序在启动后,会产生一个进程,进程是构成应用程序资源的集合。在进程内部有称之为线程的对象,线程才是真正负责执行运行命令的。

  线程:

    1:默认情况下,一个应用程序只会有一个线程,从程序开始到结束。

    2:一个进程如果有多个线程,那么多个线程将会共享进程内的资源。

    3:线程不是派生于不同的线程。

  一般来说,我们写的程序都是单线程的,但是这种程序对用户体验很不好,拿WinFrom来说,假设在单线程的情况下,用户点击某个Button执行了一个耗时操作,那么在此操作执行完成前,窗体程序是无法拖动位置的,简单来说,如果这个时候你去操作这个应用程序,那么这个应用程序的状态就会变成:未响应。造成这种问题的最根本原因是这个程序一直都是在单线执行,如果其中某个步骤耗时过长,那么后面的操作只有等待。这种写法不仅浪费资源而且还严重影响性能。而异步则可以帮我们很好的解决这一问题.

2:初识异步

  大壮是个好男人,每天晚上回家后都会煮饭,洗菜,炒菜,然后等饭熟开始吃饭,这几个步骤如果按照单线程处理方式如下:

  

 static void Main(string[] args)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
Console.WriteLine("大壮开始煮饭......");
System.Threading.Thread.Sleep(); //模拟耗时5秒
Console.WriteLine("饭煮熟了开始洗菜......");
System.Threading.Thread.Sleep(); //模拟耗时3秒
Console.WriteLine("菜洗好了,开始炒菜.......");
System.Threading.Thread.Sleep(); //模拟耗时3秒
Console.WriteLine($"开始吃饭,做饭总耗时{stopWatch.ElapsedMilliseconds}");
stopWatch.Start();
Console.ReadLine();
}

  其运行结果如下:

    

  虽然大壮把饭菜做好了,但是他的老婆不愿意了,开始说他:你说你是不是傻啊,你为什么非要等饭煮熟了采取洗菜炒菜呢?为什么就不能把饭煮了后就去洗菜炒菜,然后在等饭熟呢?大壮一拍脑袋,对啊,说改咋就改:

  

 static void Main(string[] args)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
Console.WriteLine("大壮开始煮饭......");
var isEat = CookriceAsync();
Console.WriteLine("饭煮熟了开始洗菜......");
Thread.Sleep(); //模拟耗时3秒
Console.WriteLine("菜洗好了,开始炒菜.......");
Thread.Sleep(); //模拟耗时3秒
if (isEat.Result)
Console.WriteLine($"开始吃饭,做饭总耗时{stopWatch.ElapsedMilliseconds}");
stopWatch.Stop();
Console.ReadLine();
} private static async Task<bool> CookriceAsync()
{
await Task.Run(() =>
{
Thread.Sleep();//模拟耗时5秒;
});
return true; }

异步执行

  其结果运行如下:

  

  通过上面的例子我们不难发现程序运行所耗时明显变短,其运行结果是还是一样的。当程序在执行方的时候,如果碰到异步方法,程序则会跳出异步方法继续执行没有执行的命令,异步方法的执行不会停止。当遇到异步对象点Result的时候,如果异步程序没有执行完,那么Result方法会一直阻塞程序的运行,直到其异步方法执行完毕。

3:初探async/await

  对比未使用异步和使用异步后的代码我们不难发现,我们把做饭的步骤封装成了一个CookriceAsync方法,但是该方法申明出多了一个async,并且返回结果明明是bool却变成了Task<bool>,而且代码中还冒出一个await,why?它们都是干嘛用的?别急,且听我一一道来。

  先说下异步方法的声明:

       (1)关键字:方法头使用 async 修饰。
       (2)要求:包含 N(N>0) 个 await 表达式(不存在 await 表达式的话 IDE 会发出警告),表示需要异步执行的任务。【备注】感谢 czcz1024 的修正与补充:没有的话,就和普通方法一样执行了。
       (3)返回类型:只能返回 3 种类型(void、Task 和 Task<T>)。Task 和 Task<T> 标识返回的对象会在将来完成工作,表示调用方法和异步方法可以继续执行。
       (4)参数:数量不限。但不能使用 out 和 ref 关键字。
       (5)命名约定:方法后缀名应以 Async 结尾。
       (6)其它:匿名方法和 Lambda 表达式也可以作为异步对象;async 是一个上下文关键字;关键字 async 必须在返回类型前。

  异步方法可分成三部分:

       (1)调用方法:在方法调用异步方法,然后在异步方法执行其任务的时候继续执行;
       (2)异步方法:该方法异步执行工作,然后立刻返回到调用方法;
       (3)await 表达式:用于异步方法内部,指出需要异步执行的任务。一个异步方法可以包含多个 await 表达式(不存在 await 表达式的话 IDE 会发出警告)。

  

  关于 async 关键字:

    ①在返回类型之前包含 async 关键字

    ②它只是标识该方法包含一个或多个 await 表达式,即,它本身不创建异步操作。

    ③它是上下文关键字,即可作为变量名。

  

 现在先来简单分析一下这三种返回值类型:void、Task 和 Task<T>

  1:Task<T>:调用方法要从调用中获取一个 T 类型的值,异步方法的返回类型就必须是Task<T>。调用方法从 Task 的 Result 属性获取的就是 T 类型的值。

  2:Task:不需要返回任何结果,但是需要知道异步方法的状态。不过就算方法内含有return语句,也不会返回任何东西。

  3:Void:调用方法执行异步方法,但又不需要做进一步的交互。

本文大部分文字内容来源于:http://www.cnblogs.com/liqingwen/p/5831951.html 写得不错,本篇文章只是进行一些总结。

我也来说说C#中的异步:async/await的更多相关文章

  1. Python 进阶 异步async/await

    一,前言 本文将会讲述Python 3.5之后出现的async/await的使用方法,我从上看到一篇不错的博客,自己对其进行了梳理.该文章原地址https://www.cnblogs.com/dhcn ...

  2. 异步 async & await

    1 什么是异步 异步的另外一种含义是计算机多线程的异步处理.与同步处理相对,异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程. 2 异步场景 l  不 ...

  3. 异步async/await简单应用与探究

    感谢Marco CAO指出的两点错误,已做出修改与补充 异步函数(async/await)简单应用 .NET Framework4.5提供了针对异步函数语法糖,简化了编写异步函数的复杂度. 下面通过一 ...

  4. .Net Core异步async/await探索

    走进.NetCore的异步编程 - 探索 async/await 前言: 这段时间开始用.netcore做公司项目,发现前辈搭的框架通篇运用了异步编程方式,也就是async/await方式,作为一个刚 ...

  5. .Net Core中无处不在的Async/Await是如何提升性能的?

    一.简介 Async/Await在.Net Core中真的是无处不在,到处都是异步操作,那为什么要用?有什么作用?别人说能提升性能?网上一堆文章看的绕晕了也没说清楚, 所以这里从理论,实践,原理一个个 ...

  6. C#Framework4.0支持异步async/await语法

    由于用户使用的是XP系统,但是程序里异步都是通过async/await代码来实现的,然而async/await需要Framework4.5版本才可以,而XP系统最高只能支持到Framework4.0, ...

  7. C#异步中的Task,async,await

    class Program { static void Main(string[] args) { Console.WriteLine("我是主线程,线程ID:{0}", Thre ...

  8. 请教 C# 异步 async await 问题

    各位园友,之前对C#异步只是肤浅了解,请教一个具体问题. 需求: 前台会发送一个Array,这个数组都是 id的集合,比较大.分两步,首先保存这些id,然后去调用异步方法. 可以正常返回json,也可 ...

  9. 简单的node爬虫练手,循环中的异步转同步

    简单的node爬虫练手,循环中的异步转同步 转载:https://blog.csdn.net/qq_24504525/article/details/77856989 看到网上一些基于node做的爬虫 ...

随机推荐

  1. SSL握手流程

    一.SSL是什么? 安全套接字(SSL)协议是Web浏览器和Web服务器之间安全交换信息的协议. SSL介于应用层和TCP层之间,应用层数据不再直接传递给传输层,而是传递给SSL层,SSL层对从应用层 ...

  2. delphi 文件夹权限设置(执行一个小脚本的笨办法)

    如题,研究了一天,也没再网上找到比较好的方式,自己做了一个.方法如下: 1.创建一个 cmd 命令文件.2.调用该命令. 代码如下:   S:='echo y|cacls h: /t /c /g ev ...

  3. Noip2010提高组总结

    将Noip2010重新做了一遍,第一遍做下来居然只有290分,比当年浙江的一等线低了20分,因为各种坏习惯丢掉了许多分数,Noip时需要特别注意! T1:机器翻译 第一题直接暴力,内存足够所以不用循环 ...

  4. java对象复制

    一,a和b都指向同一个对象,改变其中一个另一个也会改变 package com.ciaos; class Human{ public Human(String string, int i) { // ...

  5. HDU 3746 Cyclic Nacklace KMP

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3746 KMP算法—— AC代码: #include <iostream> #include ...

  6. [译]Stairway to Integration Services Level 11 - 日志配置

    介绍 在前一个章节我们讨论了事先行为,分享了如何操作默认的行为和时间冒泡,并且介绍了父子模型. 本文中,我们会配置SSIS日志. 进行简单及高级日志配置,存储,和检索的实验.并且生成自定义日志信息. ...

  7. Spring源码地址和相关介绍的网址

    Spring源码地址下载: https://github.com/spring-projects/spring-framework/tags >多图详解Spring框架的设计理念与设计模式:ht ...

  8. BZOJ 100题留念

  9. django开发简易博客(三)

    一.静态文件的使用 首先,新建static目录,目录下分别建立css.js.img三个子目录 修改settings.py文件 STATICFILES_DIRS = ( 'F:/web/static', ...

  10. apache下的IfModule里设置含义

    <IfModule mod_deflate.c> SetOutputFilter DEFLATE #必须的,就像一个开关一样,告诉apache对传输到浏览器的内容进行压缩 SetEnvIf ...