关于async、await、Task和Task<T>的小例子

没什么好说的,代码注释写的很详细,4个简单例子,没有高深语法,复制到编辑器运行看看注释应该就能理解了,我也是萌新,对这2个概念一直比较迷惑,分享出来共同进步。

using System;
using System.Threading.Tasks;

namespace TestAsync
{
    class TestAsync
    {
        static void Main()
        {
            DoSomething1(); //没有 Wait,如果没有 Read()等待,而 DoSomething1 延迟 5 秒输出,DoSomething3 只会延迟 1 秒,主程序会在 DoSomething1 之前结束,导致没有输出
            DoSomething2();
            DoSomething3().Wait(); //有 Wait,等 DoSomething3 执行完再继续执行,否则在没有 Read()等待的情况下,会出现 DoSomething3 没有执行完,主程序就结束了

            int i = 10;
            DoSomething4<int>(i);

            Console.WriteLine("DoSomething3全部执行,DoSomething4第一段输出之后");  //因为有Wait(),会在执行完DoSomething2之后执行
            Console.Read();         //用等待输入让主程序不结束,这样不用Wait也可以
        }

        //单独使用async,async声明表示这是一个异步方法,可以搭配await语句异步处理
        //在async声明的方法中可以使用await回调,注意async可以没有await,但是await不能没有async,有async没有await就没有异步功能,还是一个同步方法
        //await的本质是一个隐式回调,意思是创建一个等待返回的Task,返回之后继续后面的代码,所以如果有await语句可以不用显式reture
        //await必须搭配一个Task语句使用,否则报错:未找到GetAwaiter的定义
        public static async void DoSomething1()
        {
            int i = 10;
            await Task.Delay(5000); //阻塞后面语句等待延迟结束
            Console.WriteLine("DoSomething1:Task.Delay:" + 5000);
            i += 10;
            Console.WriteLine("DoSomething1:i:" + i);
        }

        //单独使用Task,Task声明的方法必须有类型是Task的返回值,否则报错
        //Task仅表示不用等待,可以继续执行后续代码,但并不是异步功能,因此主程序的调用不会等DoSomething2执行完才继续
        public static Task DoSomething2()
        {
            int i = 10;
            Task.Delay(50000);  //Delay多少都没卵用
            Console.WriteLine("DoSomething2:Task.Delay:" + 50000);
            i += 10;
            return Task.Run(() => Console.WriteLine("DoSomething2:i:" + i));
        }

        //Task、async、await三位一体才能算是异步方法,缺少任何其中一个,要么报错无法编译,要么还是同步方法,实现不了异步功能
        //Task.Delay()的作用是启动一个Task,Task开启定时器,延时指定时间
        //但是不和await一起使用,则仅仅是创建了一个Task去执行定时器任务,不会阻塞后面的语句继续执行,和DoSomething2同理
        //因此第一段输出会立即执行,不是1秒后输出
        //await会阻塞后面的语句等待返回才会继续执行,因此第二段输出在1秒后输出
        public static async Task DoSomething3()
        {
            int i = 10;
            Task.Delay(1000);   //Delay多少都没卵用
            Console.WriteLine("DoSomething3:Task.Delay:" + 1000);
            i += 10;

            await Task.Delay(1000); //阻塞后面语句等待延迟结束
            Console.WriteLine("DoSomething3:Task.Delay:" + 1000);
            Console.WriteLine("DoSomething3:i:" + i);
        }

        //那么Task<T>又怎么理解?
        //首先单独的Task<T> fun()只是一个同步方法,返回值是Task<T>,而不是T,而async Task<T> fun(){ await xxx }才是异步方法,返回的是T,不是Task<T>
        //那么async Task没有<T>,当然就是一个没有返回值的异步方法了
        public static async Task<T> DoSomething4<T>(T t)
        {
            int i = 10;
            Task.Delay(1000);
            Console.WriteLine("DoSomething4:Task.Delay:" + 1000);
            i += 10;

            await Task.Delay(1000);
            Console.WriteLine("DoSomething4:Task.Delay:" + 1000);
            Console.WriteLine("DoSomething4:i:" + i);

            Console.WriteLine("DoSomething4:T:" + typeof(T));
            return t;
        }
    }

}

//输出结果
//DoSomething3:Task.Delay:1000
//DoSomething2:Task.Delay:50000
//DoSomething2:i:20
//DoSomething3:Task.Delay:1000
//DoSomething3:i:20
//DoSomething4:Task.Delay:1000
//DoSomething3 全部执行,DoSomething4 第一段输出之后
//DoSomething4:Task.Delay:1000
//DoSomething4:i:20
//DoSomething4:T:System.Int32
//DoSomething1:Task.Delay:5000
//DoSomething1:i:20

//输出结果理解
//DoSomething1 异步延迟 5 秒输出,肯定在最后
//DoSomething2 的 Delay 没卵用,DoSomething3 的第一个 Delay 同理,都是立即执行而且没有 Wait,因此谁先谁后不一定
//DoSomething3 有 Wait(),必然是先于 DoSomething4 执行,即使 DoSomething4 第一段输出是立即执行也没用
//但是 DoSomething4 的第一段输出在主程序输出之前,所以主程序输出在 DoSomething4 第一段输出之后
//然后是 DoSomething4 的第二段输出和 T 类型输出,此时时间只过了 2 秒,而 DoSomething1 延迟 5 秒输出还没到
//到第 5 秒,输出 DoSomething1 的信息
posted @ 2021-11-14 16:37  qianxun0975  阅读(580)  评论(0编辑  收藏  举报