关于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 的信息