异步async与await的简单探究
Posted guolinjiang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异步async与await的简单探究相关的知识,希望对你有一定的参考价值。
在学习.net core的过程中,到处见到异步的使用,Task、async、await随处可见。有点疑惑,就去了解了下这个过程是怎样的。
下面是一段代码,去看看是怎么执行的吧。
一、看看异步执行的方式
static void Main(string[] args) { Console.WriteLine("我是主线程:我的ID是:" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine(); TestAsync(); Console.WriteLine("不等异步完成我先执行了哈,我的ID是:" + Thread.CurrentThread.ManagedThreadId); Console.ReadKey(); }
/// <summary> /// 异步方法 /// </summary> /// <returns></returns> static async Task TestAsync() { Console.WriteLine("我是TestAsync,调用我的线程ID是:" + Thread.CurrentThread.ManagedThreadId); await Task.Run(() => { Console.WriteLine("我是在TestAsync中开启的线程,ID是:" + Thread.CurrentThread.ManagedThreadId); }); Console.WriteLine("TestAsync开启的线程执行完后,此时的线程ID为:" + Thread.CurrentThread.ManagedThreadId); }
我们看到,主线程ID是1,然后调用TestAsync方法,注意在Main方法中,调用TestAsync我们没有使用await,因为在Main方法中不支持async。
主线程调用TestAsync方法,进到TestAsync之后,打印出调用TestAsync方法的线程的ID。然后遇到Task.Run开启新的线程,ID为3。Task.Run之前有await,
注意:await会阻塞当前线程,就是ID为3的线程,并且释放调用TestAsync方法的线程,也即是主线程(ID为1),这个时候我们看到"不等异步完成我先执行了哈,我的ID是:1"
输出在"TestAsync开启的线程执行完后,此时的线程ID为:4"之前。这就说明了,TestAsync方法中await释放了主线程,同时Task.Run开启了一个新的线程。
Task.Run开启的线程是从线程池中取出的空闲线程。我运行几次,发现最后一个输出的结果不一样。如下图:
这应该说明,Task.Run开启线程后,await后的代码,是会重新开启一个线程去执行的。
二、看看await是怎么阻塞之后的代码的。
static void Main(string[] args) { Console.WriteLine("我是主线程:我的ID是:" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine(); TestAsync(); Console.WriteLine("不等异步完成我先执行了哈,我的ID是:" + Thread.CurrentThread.ManagedThreadId); Console.ReadKey(); }
/// <summary> /// 异步方法 /// </summary> /// <returns></returns> static async Task TestAsync() { Console.WriteLine("我是TestAsync,调用我的线程ID是:" + Thread.CurrentThread.ManagedThreadId); await TestAsync2(); Console.WriteLine("我被阻塞了,在TestAsync2执行之后才会执行,现在的线程ID是:" + Thread.CurrentThread.ManagedThreadId); await Task.Run(() => { Console.WriteLine("我是在TestAsync中开启的线程,ID是:" + Thread.CurrentThread.ManagedThreadId); }); Console.WriteLine("TestAsync开启的线程执行完后,此时的线程ID为:" + Thread.CurrentThread.ManagedThreadId); }
static async Task TestAsync2() { Console.WriteLine(); Console.WriteLine("我是TestAsync2,调用我的线程ID是:" + Thread.CurrentThread.ManagedThreadId); await Task.Run(() => { Console.WriteLine("我是在TestAsync2中开启的线程,ID是:" + Thread.CurrentThread.ManagedThreadId); int num = 0; for (int i = 0; i < 1000000; i++) { num += 1; } Console.WriteLine($"在TestAsync2中执行一个耗点儿时间的操作,num的值是{num}"); }); }
我们看到在TestAsync中调用TestAsync2前面加了await,"我被阻塞了,在TestAsync2执行之后才会执行,现在的线程ID是:3"
在TestAsync2方法执行之后,才输出。并且这个时候主线程被释放掉了,去输出"不等异步完成我先执行了哈,我的ID是:1"。
好了,暂时就理解了这么多,肯定有不对的地方,欢迎大家指正,时间不早了,早点休息,做个佛系养生的程序员,
以上是关于异步async与await的简单探究的主要内容,如果未能解决你的问题,请参考以下文章