暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

对于async和await的使用方式、作用效果不怎么理解 ?没关系,初步看这篇就够了

熊泽有话说 2022-12-12
222

 成功一定有方法,失败一定有原因。

目录

  • 结论

  • 概述

    • async(C# 参考)

    • await(C# 参考)

  • 作用及基本用法

  • 实现多任务顺序执行且不阻塞

    • 1.同步执行

    • 2.并行执行

    • 3.并行且可指定顺序执行

  • 总结

  • 参考文献

 


结论

同步还是异步,区别如下:

  • 同步:你使用 await 修饰符去调用一个异步(async)方法(是异步方法,不过是阻塞式的,可简单理解为同步);

  • 异步:你获取异步方法返回的 Task,就是异步(后文有代码示例);

  • 可以实现多任务执行顺序执行且不阻塞。


概述


async(C# 参考)

async 是“异步”的简写,使用 async 修饰符可将方法、lambda 表达式或匿名方法指定为异步。

如果对方法或表达式使用此修饰符,则其称为异步方法 。

如下示例定义了一个名为 ExampleMethodAsync
 的异步方法:

    public async Task<int> ExampleMethodAsync()
    {
    //...
    }
    复制

     

    await(C# 参考)

    await 运算符暂停对其所属的 async 方法的求值,直到其操作数表示的异步操作完成。

    异步操作完成后,await 运算符将返回操作的结果(如果有)。

    当 await 运算符应用到表示已完成操作的操作数时,它将立即返回操作的结果,而不会暂停其所属的方法。

     await 运算符不会阻止计算异步方法的线程。

    当 await 运算符暂停其所属的异步方法时,控件将返回到方法的调用方。

    官网说的话是不是听不明白?没关系,你就理解为添加了await 修饰符后,必须要等调用返回后才能继续执行下一步。

    如下示例:

      public async Task<int> ExampleMethodAsync()
      {
      //...
      //这添加了await,执行到这里需要等待MethodAwiat方法执行完成后才会往下继续执行。
      int result = await MethodAwiat();
      //...


      }
      public async Task<int> MethodAwiat()
      {
      //...
      }
      复制


      作用及基本用法

      await和async可以简化我们异步编程,也可以让我们以一种类似同步编程的方式来进行异步编程。

      另外当我们需要不阻塞主线程异步执行,但又要有顺序的执行相关代码的时候,await/async就可以排上用场。

      基本用法如下示例:

        /// <summary>
        /// 可异步可同步
        /// </summary>
        /// <returns></returns>
        public async Task<string> TestAsync()
        {
        Thread.Sleep(3000);
        Task<string> task = new Task<string>(() =>
        {
        return "主程序返回后我还在执行数据:我是复杂的异步执行的方法,不阻碍主程序执行。。。。。";
        });
        task.Start();
        return await task;
        }


        await 使得任务同步
        public async void T1()
        {
        使用 await 关键字,代表等待执行完成,同步
        string time = await TestAsync();
        Console.WriteLine(time);
        Console.WriteLine("执行完毕");
        }


        直接获得返回的 Task,实现异步
        public void T2()
        {
        获取 Task 任务对象,后面的逻辑过程可以弄成异步
        Task<string> task = TestAsync();


        这里可以处理其它事情,处理完毕后,再获取执行结果
        Console.WriteLine("执行完毕");


        Console.WriteLine(task.Result);
        }
        复制

         


        实现多任务顺序执行且不阻塞

        以微软文档的做早餐的案例加以简化来讲解 【使用Async和Await可以实现多任务顺序执行且不阻塞】。

        主线任务任务:倒橙汁 -> 烤面包 -> 煎培根 -> 煎鸡蛋 -> 倒咖啡。


        1.同步执行

        我们任务逐步顺序执行如下,耗时:17064毫秒(17.064秒):

          using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter;
          using System;
          using System.Diagnostics;
          using System.Threading;


          namespace ConsoleApp1
          {
          class Program
          {


          static void Main(string[] args)
          {
          Stopwatch stopwatch = new Stopwatch();
          stopwatch.Start();
          PourOJ();
          PourCoffee();
          ToastBread();
          FryBacon();
          FryEggs();
          Console.WriteLine("早餐已经做完!");
          stopwatch.Stop();
          Console.WriteLine($"做早餐总计耗时:{stopwatch.ElapsedMilliseconds}");
          Console.ReadLine();


          }


          //倒橙汁
          private static void PourOJ()
          {
          Thread.Sleep(1000);
          Console.WriteLine("倒一杯橙汁");
          }


          //烤面包
          private static void ToastBread()
          {
          Console.WriteLine("开始烤面包");
          Thread.Sleep(3000);
          Console.WriteLine("烤面包好了");


          }


          //煎培根
          private static void FryBacon()
          {
          Console.WriteLine("开始煎培根");
          Thread.Sleep(6000);
          Console.WriteLine("培根煎好了");
          }
          //煎鸡蛋
          private static void FryEggs()
          {
          Console.WriteLine("开始煎鸡蛋");
          Thread.Sleep(6000);
          Console.WriteLine("鸡蛋好了");
          }


          //倒咖啡
          private static void PourCoffee()
          {
          Thread.Sleep(1000);
          Console.WriteLine("倒咖啡");
          }
          }
          }
          复制

           

          2.并行执行

          如果此时我们每一项任务都有一个单独的人去完成,将会缩短时间将近3倍(当然不能单纯的用时间量化他),

          如下,耗时6041毫秒(6.041秒):

            using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter;
            using System;
            using System.Collections.Generic;
            using System.Diagnostics;
            using System.Threading;
            using System.Threading.Tasks;


            namespace ConsoleApp1
            {
            class Program
            {


            static void Main(string[] args)
            {
            Test();
            Console.ReadLine();


            }


            private static void Test()
            {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            List<Task> tasks = new List<Task>() { PourOJ(), ToastBread(), FryBacon(), FryEggs(), PourCoffee() };
            Task.WhenAll(tasks).ContinueWith((t) =>
            {
            Console.WriteLine("早餐已经做完!");
            stopwatch.Stop();
            Console.WriteLine($"做早餐总计耗时:{stopwatch.ElapsedMilliseconds}");
            });
            }


            //倒橙汁
            private static async Task PourOJ()
            {
            await Task.Delay(1000);
            Console.WriteLine("倒一杯橙汁");
            }


            //烤面包
            private static async Task ToastBread()
            {
            Console.WriteLine("开始烤面包");
            await Task.Delay(3000);
            Console.WriteLine("烤面包好了");


            }


            //煎培根
            private static async Task FryBacon()
            {
            Console.WriteLine("开始煎培根");
            await Task.Delay(6000);
            Console.WriteLine("培根煎好了");
            }
            //煎鸡蛋
            private static async Task FryEggs()
            {
            Console.WriteLine("开始煎鸡蛋");
            await Task.Delay(6000);
            Console.WriteLine("鸡蛋好了");
            }


            //倒咖啡
            private static async Task PourCoffee()
            {
            await Task.Delay(1000);
            Console.WriteLine("倒咖啡");
            }
            }
            }
            复制

             


            3.并行且可指定顺序执行

            但是我们不可能每次做早餐都有那么多人同时做,

            需求变更:如果现在要求,先倒橙汁,然后倒咖啡,其余的操作并行执行,应该如何操作呢?

            只需将以上案例的主线程Test 方法修改如下,其他的不变,耗时8073毫秒(8.073秒):

              private static async void Test()
              {
              Stopwatch stopwatch = new Stopwatch();
              stopwatch.Start();
              await PourOJ(); //倒橙汁
              await PourCoffee(); //然后倒咖啡
              List<Task> tasks = new List<Task>() { ToastBread(), FryBacon(), FryEggs() };//子任务List
              await Task.WhenAll(tasks); //其余的并行操作
              Console.WriteLine("早餐已经做完!");
              stopwatch.Stop();
              Console.WriteLine($"做早餐总计耗时:{stopwatch.ElapsedMilliseconds}");
              }
              复制


              总结

              我们发现,用好了async和await确实很节省时间。

              大家可以想想怎么优雅的在异步里面开多线程(多主线程多子线程)最节省时间。


              参考文献

              • 使用 Async 和 Await 的异步编程(C# )

              • async(C# 参考)

              • await(C# 参考)

               


               

              喜欢就点赞加关注。

              欢迎关注订阅微信公众号【熊泽有话说】,更多好玩易学知识等你来取
              作者:熊泽-学习中的苦与乐
              公众号:熊泽有话说

              QQ群:711838388
              您可以随意转载、摘录,但请在文章内注明作者和原文链接。  

               


              文章转载自熊泽有话说,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论