zoukankan      html  css  js  c++  java
  • 我也来说说C#中的异步:async/await

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

    1:什么是异步

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

      线程:

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

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

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

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

    2:初识异步

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

      

     1 static void Main(string[] args)
     2 {
     3             var stopWatch = new Stopwatch();
     4             stopWatch.Start();
     5             Console.WriteLine("大壮开始煮饭......");
     6             System.Threading.Thread.Sleep(5000);  //模拟耗时5秒
     7             Console.WriteLine("饭煮熟了开始洗菜......");
     8             System.Threading.Thread.Sleep(3000); //模拟耗时3秒
     9             Console.WriteLine("菜洗好了,开始炒菜.......");
    10             System.Threading.Thread.Sleep(3000);  //模拟耗时3秒
    11             Console.WriteLine($"开始吃饭,做饭总耗时{stopWatch.ElapsedMilliseconds}");
    12             stopWatch.Start();
    13             Console.ReadLine();
    14}

      其运行结果如下:

        

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

      

     1 static void Main(string[] args)
     2         {
     3             var stopWatch = new Stopwatch();
     4             stopWatch.Start();
     5             Console.WriteLine("大壮开始煮饭......");
     6             var isEat = CookriceAsync();
     7             Console.WriteLine("饭煮熟了开始洗菜......");
     8             Thread.Sleep(3000); //模拟耗时3秒
     9             Console.WriteLine("菜洗好了,开始炒菜.......");
    10             Thread.Sleep(3000);  //模拟耗时3秒
    11             if (isEat.Result)
    12                 Console.WriteLine($"开始吃饭,做饭总耗时{stopWatch.ElapsedMilliseconds}");
    13             stopWatch.Stop();
    14             Console.ReadLine();
    15         }
    16 
    17 
    18         private static async Task<bool> CookriceAsync()
    19         {
    20             await Task.Run(() =>
    21             {
    22                 Thread.Sleep(5000);//模拟耗时5秒;  
    23             });
    24             return true;
    25 
    26         }
    异步执行

      其结果运行如下:

      

      通过上面的例子我们不难发现程序运行所耗时明显变短,其运行结果是还是一样的。当程序在执行方的时候,如果碰到异步方法,程序则会跳出异步方法继续执行没有执行的命令,异步方法的执行不会停止。当遇到异步对象点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 写得不错,本篇文章只是进行一些总结。

  • 相关阅读:
    如何通过命令行窗口查看sqlite数据库文件
    eclipse自动补全的设置
    文本装饰
    注释和特殊符号
    文本装饰
    网页背景
    通过ArcGIS Server admin 查看和删除已注册的 Web Adaptor
    通过 ArcGIS Server Manager 查看已安装的 Web Adaptor
    通过 ArcGIS Server Manager 验证 DataStore
    Windows上安装ArcGIS Enterprise——以 Windows Server 2012 R2上安装 ArcGIS 10.8为例
  • 原文地址:https://www.cnblogs.com/dazhuangtage/p/5891104.html
Copyright © 2011-2022 走看看