• 理解C#里的async和await


    世界很单纯,复杂的是人呐~

    async和await也是如此。语法和含义很简单,程序员想多了,这东西就显得特别复杂。

    async

    含义:异步。它修饰的方法里,通常有其他异步操作。普通操作(通常是前半截)执行完了,控制权就返回“调用它的方法(主方法)”了(通常带回一个Task)。当异步操作(通常是后半截)执行完之后,主方法可以从它返回的Task里拿需要的东西(也可以不拿)。前后半截的分界线,就是await。

      ps:这东西一般出现在方法头部,但不属于方法签名的一部分。也就是说,不能出现在接口和抽象类的方法说明中,可以出现在实现的方法头。

    await

      含义:在可等待方法中,await就是前后两段代码的分界线。它前面的代码被编译成一个方法,它和它后面的代码被编译成另一个方法。第一个方法,通常由主线程执行;第二个方法,通常由新建的线程(一般在异步嵌套调用的最里层新建)执行。它等待的,是一个异步操作的结果。

      注意:子方法运行到await的时候,主方法继续执行,而子方法等待它等待的结果,然后执行它后面的语句。

    用途

      通常,设计一个异步(可等待)方法,就是为了方便别人调用它,它执行异步操作的时候,别人还能干自己的事。


    问题来了:怎么用?

    不止是语法问题,还要跟我们平时的编程习惯……最好是同步编程习惯贴合,才舒适。

    先看一段耗时操作:

    先花1秒,计算n!

    static int jc(int x)
    {
        int y = 1;
        Thread.Sleep(1000);
        for (int i = 2; i <=x; i++)
        {
            y *= i;
        }
        return y;
    }

    针对耗时操作,肯定会想到异步调用。常规异步调用:

    var t=Task.Run(() => jc(5));//求5!,开始算吧
    Console.WriteLine("我忙我的");
    Console.WriteLine($"5!={t.Result}");

    既然耗时操作,一般都是异步调用。那我就给它包装个异步方法,以期更好调用:

    static async Task<int> jc1(int x)
    {
        var t = Task.Run(() => jc(x));
        Console.WriteLine($"异步计算{x}!已经开始了,主程序继续...");
        await t;
        Console.WriteLine($"{x}!算完了");
        return t.Result;
        //return await Task.Run(() => jc(x));//极简写法
    }

    遇到await,主程序得到一个“必有int返回值”的承诺,就继续执行。子程序当Task执行完毕的时候,await向下继续执行。

    调用方法就可以写成:

    var t = jc1(5);//异步求5!,开始算吧,我继续。。。
    Console.WriteLine("我忙我的");
    Console.WriteLine($"5!={t.Result}");

    第一行开始计算,第三行索要结果(谁让你承诺必有结果呢)。少了task,更符合人类习惯了。

    第三行“t.Result”那里如果是“await t”,这个主方法也就是异步方法了。 


    总结:

    一、无论是自己写的,还是微软写的异步方法(下面叫做S)里,必然有一个多线程的所谓“耗时操作”。

    二、调用时,可以

    1. await S();阻塞式异步调用;
    2. S().wait();阻塞式同步调用;
    3. var t=S();/*并行操作*/;await t;并行异步调用;
    4. var t=S();/*并行操作*/;t.wait();并行同步调用。

    所谓异步/同步调用,即所在的方法是异步/同步方法。

    三、不管套多少层的异步,一般也就两个线程。

  • 相关阅读:
    Es spring data jpa 修改连接配置
    object转map类型
    记一次项目中yaml文档引发的惨案 (#yaml文档格式#yaml中'-'的作用)
    02-方法重载
    01-数据类型分类
    Centos 7 Sublime 安装 package control
    修改AdminLTE左侧菜单展开延迟
    【Flask】Flask Restful api
    【Flask】Flask常用信号
    【Flask】Flask上下文
  • 原文地址:https://www.cnblogs.com/wanjinliu/p/15554246.html
Copyright © 2020-2023  润新知