这几天终于弄懂了async和await的模式,也搞明白了一直在内心面积压着的许多问题,因此写一篇博客来和你们分享一下。编程
关于异步机制我认为只要记住的如下几点,就能够弄明白了:异步
1.我认为async和awwait两个修饰符中最关键的是await,async是因为方法中包含await修饰符以后才在方法定义中添加的,代表这个方法是一个异步方法。async
2.await只能用来修饰Task、Task<TResult>、ValueTask 或 ValueTask<TResult>这些类型的变量或者方法,他是一个分裂符,咱们须要记住的最关键一点是当程序进行到await的时候,方法会暂时返回,而await字符以后的内容会等await这一行返回后继续执行。函数
3.在控制台应用中,await以前的内容是一个线程执行,await以及awiat以后的内容会在另外一个线程中执行。学习
咱们在编程时不少时候其实都用错了aiwat,这也致使我一开始学习的时候对await产生了很是多的疑问,以致于一直都没有弄清楚,好比:spa
int bytesLoaded = await DownloadDocsMainPageAsync();
这个几乎是咱们写代码时见到最多的用法了,在主方法中使用await 来作一些request的请求,当时就在想await不是异步吗,但为何还要在这里等待这个输出才进行下一步的执行呢?那么异步是异步到哪里了呢?其实这种使用方式并无体现出异步的特点,只是由于request中不少方法是异步方法而为了获取结果才这么写的,真正的使用方式实际上是下面这样的:线程
Task<int> downloading = DownloadDocsMainPageAsync(); //省略代码,这里有一些处理方式// int bytesLoaded = await downloading;
异步是在咱们处理一件事的时候能够同时进行着另外一件事,下图说明了上面代码在主方法中的调用逻辑:调试
另外我写了一个异步的demo,这个方法里面有两个异步的例子,你们有兴趣的话能够在本地本身调试去感觉一下异步的实现方式和调用的顺序,方便你们理解:code
//private static void Main(string[] args) //{ // //Console.WriteLine("111 balabala. My Thread ID is :" + Thread.CurrentThread.ManagedThreadId); // //var r = AsyncMethod(); // //Console.WriteLine(r); // //Console.WriteLine("222 balabala. My Thread ID is :" + Thread.CurrentThread.ManagedThreadId); // //Thread.Sleep(10000); //} public static async Task Main() { Task<int> downloading = DownloadDocsMainPageAsync(); Console.WriteLine($"{nameof(Main)}: Launched downloading."); Console.WriteLine("main1 " + Thread.CurrentThread.ManagedThreadId); int bytesLoaded = await downloading; Console.WriteLine("main2 " + Thread.CurrentThread.ManagedThreadId); Console.WriteLine($"{nameof(Main)}: Downloaded {bytesLoaded} bytes."); } private static async Task<int> DownloadDocsMainPageAsync() { Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: About to start downloading."); Console.WriteLine("sub1 " + Thread.CurrentThread.ManagedThreadId); var client = new HttpClient(); byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/"); Console.WriteLine("sub2 " + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: Finished downloading."); return content.Length; } private async static Task<String> AsyncMethod() { var ResultFromTimeConsumingMethod = TimeConsumingMethod(); string Result = await ResultFromTimeConsumingMethod + " + AsyncMethod. My Thread ID is :" + Thread.CurrentThread.ManagedThreadId; Console.WriteLine(Result); Console.WriteLine(Thread.CurrentThread.ManagedThreadId); return Result; //返回值是Task的函数能够不用return } //这个函数就是一个耗时函数,多是IO操做,也多是cpu密集型工做。 private static Task<string> TimeConsumingMethod() { var task = Task.Run(() => { Console.WriteLine("Helo I am TimeConsumingMethod. My Thread ID is :" + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); Console.WriteLine("Helo I am TimeConsumingMethod after Sleep(5000). My Thread ID is :" + Thread.CurrentThread.ManagedThreadId); return "Hello I am TimeConsumingMethod"; }); return task; }
最后附上我参考的一些内容:blog
https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/await
上面demo有一个被注释了的main方法是我参考的另外一个大神的博客,正是读了他的博客才让我恍然大悟(虽然里面的其余叙述也不是很是准确),可是在理解async和await方面,这篇博客真正点醒了我,很惋惜我当时读博客的时候并无收藏,后面也没有找到博客地址,可是仍是要在这里感谢他。