NetCore之Async_Await
网上关于async/await的知识有很多,看了很多但不如自己实践一遍来得快,所以这里记录下我的理解和大家学习下。
因为await会时被修饰的代码处于等待状态,就相当于阻塞那段代码.
会有阻塞转移的情况发生
首先以最简单的同步方法来开始如下
网上关于async / await的知识有很多, 看了很多但不如自己实践一遍来得快, 所以这里记录下我的理解和大家学习下。 首先以最简单的同步方法来开始如下 private static void Test() { Console.WriteLine(2); GetV(); Console.WriteLine(6); } private static void GetV() { Console.WriteLine(3); Console.WriteLine(4); Console.WriteLine(5); } static void Main(string[] args) { Console.WriteLine(1); Test(); Console.WriteLine(7); }
输出如下:这个就是按照同步的方法,一步步的去执行的
当时当我们简单的使用Task.Run时
private static void Test() { Console.WriteLine(2); GetV(); Console.WriteLine(6); } private static void GetV() { Console.WriteLine(3); Task.Run(() => { Thread.Sleep(10000); Console.WriteLine(4); }); Console.WriteLine(5); } static void Main(string[] args) { Console.WriteLine(1); Test(); Console.WriteLine(7); }
因为Task分配了新的线程,所以4会被最晚打印出来;因为"4" ,“睡”了10s
这时候我们使用async/await呢?
private static async Task Test() { Console.WriteLine(2); await GetV(); Console.WriteLine(6); } private static async Task GetV() { Console.WriteLine(3); await Task.Run(() => { Thread.Sleep(10000); Console.WriteLine(4); }); Console.WriteLine(5); } static void Main(string[] args) { Console.WriteLine(1); var v = Test();//这里注意,虽然Test是异步方法,但是在Main函数中,并没有异步来修饰它 Console.WriteLine(7); }
所以这个时候打印结果:
因为被await修饰的代码处于等待状态,就相当于阻塞那段代码,
Test方法里面执行到await时就会等待Getv的方法的执行,就会阻塞Test方法,
(看好了,是Getv(),是在Test()里调用的,阻塞了Test方法)
但是不会阻塞Main方法,可以理解为await将阻塞的控制权交给了Test方法。
这里有个我的理解是:Main方法启动,照常打印出来1
然后就是执行到了Test()方法了,这个时候TEST()方法里的GETV()方法是被await,
GETV中是照样输出3
然后等待10s输出4,再输出5;
然后再输出6
就是理解一条:被await的就会等待, 一开始是修饰的await GetV()----》await Task.Run(),这个等待转移了, 最终将阻塞的控制权转移到Task.Run()上面了, 所以3还是同步输出了。 因为6在await GetV()下面,所以要等待异步执行完毕。 1237 456
但是当我们把Test的await去掉了,这时候Test方法就没有了阻塞的权限,而是去寻找下一个await来转移控制权,如下
这个时候不会阻塞Test了。而是直接寻找到Task.Run(),这个方法了。因为“3”在阻塞线程前面,所以还是同步输出了。“5”在后面,所以还是要在“4”之后输出
private static void Test() { Console.Out.WriteLine(2); await GetV(); Console.Out.WriteLine(6); } private static async Task GetV() { Console.Out.WriteLine(3); await Task.Run(() => { Thread.Sleep(10000); Console.WriteLine(4); }); Console.Out.WriteLine(5); } static void Main(string[] args) { Console.Out.WriteLine(1); Test(); Console.Out.WriteLine(7); string str = Console.ReadLine(); }
1236745
如果在main方法里面使用Task.GetAwaiter或者Task.Result
这两个东西我的理解就是阻塞线程,等待异步返回结果,
但是它阻塞的是当前的方法
当前方法:就是A方法现在在哪个方法体内,那这个方法就是当前方法;
(GetV(),在Test()方法内,那么Test()就是当前方法)
如下代码
private static async Task Test() { Console.Out.WriteLine(2); GetV(); Console.Out.WriteLine(6); } private static async Task GetV() { Console.Out.WriteLine(3); await Task.Run(() => { Thread.Sleep(10000); Console.WriteLine(4); }); Console.Out.WriteLine(5); } static void Main(string[] args) { Console.Out.WriteLine(1); Test().GetAwaiter().GetResult(); Console.Out.WriteLine(7); string str = Console.ReadLine(); }
它只会阻塞main方法的,对于Test方法它是无法阻塞的,Test方法仍然会异步执行
4,5仍然以异步的方法打印出来,所以打印结果如下
人各有命,上天注定,有人天生为王,有人落草为寇。脚下的路,如果不是你自己的选择,那么旅程的终点在哪,也没人知道。你会走到哪,会遇到谁,都不一定。