我也来说说C#中的异步:async/await

  最近看了一些园友们写的有关于异步的文章,受益匪浅,写这篇文章的目的是想把自己之前看到的文章做一个总结,同时也希望通过更加通俗易懂的语言让大家了解"异步"编程。

1:什么是异步

  应用程序在启动后,会产生一个进程,进程是构成应用程序资源的集合。在进程内部有称之为线程的对象,线程才是真正负责执行运行命令的。

  线程:

    1:默认情况下,一个应用程序只会有一个线程,从程序开始到结束。

    2:一个进程如果有多个线程,那么多个线程将会共享进程内的资源。

    3:线程不是派生于不同的线程。

  一般来说,我们写的程序都是单线程的,但是这种程序对用户体验很不好,拿WinFrom来说,假设在单线程的情况下,用户点击某个Button执行了一个耗时操作,那么在此操作执行完成前,窗体程序是无法拖动位置的,简单来说,如果这个时候你去操作这个应用程序,那么这个应用程序的状态就会变成:未响应。造成这种问题的最根本原因是这个程序一直都是在单线执行,如果其中某个步骤耗时过长,那么后面的操作只有等待。这种写法不仅浪费资源而且还严重影响性能。而异步则可以帮我们很好的解决这一问题.

2:初识异步

  大壮是个好男人,每天晚上回家后都会煮饭,洗菜,炒菜,然后等饭熟开始吃饭,这几个步骤如果按照单线程处理方式如下:

  

 1 static void Main(string[] args)
 2 {
 3             var stopWatch = new Stopwatch();
 4             stopWatch.Start();
 5             Console.WriteLine("大壮开始煮饭......");
 6             System.Threading.Thread.Sleep(5000);  //模拟耗时5秒
 7             Console.WriteLine("饭煮熟了开始洗菜......");
 8             System.Threading.Thread.Sleep(3000); //模拟耗时3秒
 9             Console.WriteLine("菜洗好了,开始炒菜.......");
10             System.Threading.Thread.Sleep(3000);  //模拟耗时3秒
11             Console.WriteLine($"开始吃饭,做饭总耗时{stopWatch.ElapsedMilliseconds}");
12             stopWatch.Start();
13             Console.ReadLine();
14}

  其运行结果如下:

    

  虽然大壮把饭菜做好了,但是他的老婆不愿意了,开始说他:你说你是不是傻啊,你为什么非要等饭煮熟了采取洗菜炒菜呢?为什么就不能把饭煮了后就去洗菜炒菜,然后在等饭熟呢?大壮一拍脑袋,对啊,说改咋就改:

  

 1 static void Main(string[] args)
 2         {
 3             var stopWatch = new Stopwatch();
 4             stopWatch.Start();
 5             Console.WriteLine("大壮开始煮饭......");
 6             var isEat = CookriceAsync();
 7             Console.WriteLine("饭煮熟了开始洗菜......");
 8             Thread.Sleep(3000); //模拟耗时3秒
 9             Console.WriteLine("菜洗好了,开始炒菜.......");
10             Thread.Sleep(3000);  //模拟耗时3秒
11             if (isEat.Result)
12                 Console.WriteLine($"开始吃饭,做饭总耗时{stopWatch.ElapsedMilliseconds}");
13             stopWatch.Stop();
14             Console.ReadLine();
15         }
16
17
18         private static async Task<bool> CookriceAsync()
19         {
20             await Task.Run(() =>
21             {
22                 Thread.Sleep(5000);//模拟耗时5秒;
23             });
24             return true;
25
26         }

异步执行

  其结果运行如下:

  

  通过上面的例子我们不难发现程序运行所耗时明显变短,其运行结果是还是一样的。当程序在执行方的时候,如果碰到异步方法,程序则会跳出异步方法继续执行没有执行的命令,异步方法的执行不会停止。当遇到异步对象点Result的时候,如果异步程序没有执行完,那么Result方法会一直阻塞程序的运行,直到其异步方法执行完毕。

3:初探async/await

  对比未使用异步和使用异步后的代码我们不难发现,我们把做饭的步骤封装成了一个CookriceAsync方法,但是该方法申明出多了一个async,并且返回结果明明是bool却变成了Task<bool>,而且代码中还冒出一个await,why?它们都是干嘛用的?别急,且听我一一道来。

  先说下异步方法的声明:

   (1)关键字:方法头使用 async 修饰。

   (2)要求:包含 N(N>0) 个 await 表达式(不存在 await 表达式的话 IDE 会发出警告),表示需要异步执行的任务。【备注】感谢 czcz1024 的修正与补充:没有的话,就和普通方法一样执行了。

   (3)返回类型:只能返回 3 种类型(void、Task 和 Task<T>)。Task 和 Task<T> 标识返回的对象会在将来完成工作,表示调用方法和异步方法可以继续执行。

  (4)参数:数量不限。但不能使用 out 和 ref 关键字。

  (5)命名约定:方法后缀名应以 Async 结尾。

   (6)其它:匿名方法和 Lambda 表达式也可以作为异步对象;async 是一个上下文关键字;关键字 async 必须在返回类型前。

  异步方法可分成三部分:

   (1)调用方法:在方法调用异步方法,然后在异步方法执行其任务的时候继续执行;

   (2)异步方法:该方法异步执行工作,然后立刻返回到调用方法;

  (3)await 表达式:用于异步方法内部,指出需要异步执行的任务。一个异步方法可以包含多个 await 表达式(不存在 await 表达式的话 IDE 会发出警告)。

  

  关于 async 关键字:

    ①在返回类型之前包含 async 关键字

    ②它只是标识该方法包含一个或多个 await 表达式,即,它本身不创建异步操作。

    ③它是上下文关键字,即可作为变量名。

  

 现在先来简单分析一下这三种返回值类型:void、Task 和 Task<T>

  1:Task<T>:调用方法要从调用中获取一个 T 类型的值,异步方法的返回类型就必须是Task<T>。调用方法从 Task 的 Result 属性获取的就是 T 类型的值。

  2:Task:不需要返回任何结果,但是需要知道异步方法的状态。不过就算方法内含有return语句,也不会返回任何东西。

  3:Void:调用方法执行异步方法,但又不需要做进一步的交互。

时间: 2024-10-13 22:21:51

我也来说说C#中的异步:async/await的相关文章

.net4.5的异步 async await 和Task

首先应该明白Task的概念-----任务 //这是一种优于Thread,甚至是ThreadPool的东西 而且是默认异步 再来理解async和await: 1.async只是配合await,用来声明异步方法的关键字: 2.async和await之间,await才是关键,直接含义——"异步等待",主线程运行至异步方法内的await处,一般情况下主线程会立即返回上层方法,而await处后续的任务(方法)会新开线程继续执行,新开线程在执行“等待”出任务(方法)结果后,会接着运行完异步方法内a

异步async/await简单应用与探究

异步函数(async/await)简单应用 .NET Framework4.5提供了针对异步函数语法糖,简化了编写异步函数的复杂度. 下面通过一个简单的示例,介绍.NET Framework4.5对异步函数的支持. 示例代码 class Program { static void Main(string[] args) { EasyAsyncAwait(); Console.ReadLine(); } static async void EasyAsyncAwait() { //① Task<s

Redis中的异步Async

你了解redis里面的async与没有async的方法有什么区别吗 比如,HashExistsAsync和HashExists 一个异步的一个同步的吧 他这个异步具体是指什么的异步呢 带async的执行了这一句就直接往下执行了 不必等他执行完 里面是另外开启了一个线程

C#异步中的Task,async,await

class Program { static void Main(string[] args) { Console.WriteLine("我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId); TestAsync(); Console.ReadLine(); } static async void TestAsync() { Console.WriteLine("调用GetReturnResult()之前,线程ID:{0

asp.net 异步(async/await)中访问HttpContext的问题

以web api上传文件的官方例子为例: await Request.Content.ReadAsMultipartAsync(provider); 项目里面多处用到session,包括在其他类库中通过HttpContext获取Session对象,在await之后,直接访问Session均为空了. 怎么办,文件得上传啊. 网络搜索无果,后来发现HttpContext竟然支持Set方法,那么在await之前存储HttpContext的引用,在await之后将引用再赋给HttpContext,这样似

异步async await 相关知识点总结以及代码练习

<script> const setTimeoutToPromise = duration => new Promise(resolve => { setTimeout(resolve, duration) }) export default { data() { return { mysrc: true } }, methods: { s1(a){ console.log(a) }, s2(a){ console.log(a) }, s3(a){ console.log(a) }

Async Await异步调用WebApi

先铺垫一些基础知识 在 .net 4.5中出现了 Async Await关键字,配合之前版本的Task 来使得开发异步程序更为简单易控. 在使用它们之前 我们先关心下 为什么要使用它们.好比 一个人做几件事,那他得一件一件的做完,而如果添加几个人手一起帮着做 很显然任务会更快的做好.这就是并行的粗浅含义. 在程序中,常见的性能瓶颈在于 NetWork I/O 瓶颈 , CPU 瓶颈, 数据库I/O瓶颈,这些瓶颈使得我们的程序运行的很慢,我们想办法去优化.因为并行开发本身就加重CPU负担,所以一般

js异步回调Async/Await与Promise区别 新学习使用Async/Await

Promise,我们了解到promise是ES6为解决异步回调而生,避免出现这种回调地狱,那么为何又需要Async/Await呢?你是不是和我一样对Async/Await感兴趣以及想知道如何使用,下面一起来看看这篇文章:Async/Await替代Promise的6个理由. 什么是Async/Await? async/await是写异步代码的新方式,以前的方法有回调函数和Promise. async/await是基于Promise实现的,它不能用于普通的回调函数. async/await与Prom

ASP.NET MVC中使用异步控制器

线程池 一直想把项目改写成异步,但是ASP.NETMVC3下写的过于繁琐,.NET 4.5与ASP.NET MVC下代码写起来就比较简单了, MS好像也一直喜欢这样搞,每一个成熟的东西,都要演变好几个版本,才能趋于规范. ASP.NET MVC 中为什么需要使用异步呢,IIS有一个线程池来处理用户的请求,当一个新的请求过来时,将调度池中的线程以处理该请求,然而,但并发量很高的情况下,池中的线程已经不能够满足这么多的请求时候,池中的每一个线程都处于忙的状态则在处理请求时将阻塞处理请求的线程,并且该