当前位置:首页 > Windows程序 > 正文

[C#] 谈谈异步编程async await

2021-03-29 Windows程序

  为什么需要异步,异步对可能起阻止作用的活动(例如,应用程序访问 Web 时)至关重要。 对 Web 资源的访问有时很慢或会延迟。 如果此类活动在同步过程中受阻,则整个应用程序必须等待。 在异步过程中,应用程序可继续执行不依赖 Web 资源的其他工作,直至潜在阻止任务完成。

  本节将一步一步带领大家理解async和await。

  期间会有

  ,,,,,以及线程中常涉及到的和,以及微软提供的

  推荐先看后顶,学的更快!

Hello World

static void Main(string[] args) { new Thread(Test) { IsBackground = false }.Start(); //.Net 在1.0的时候,就已经提供最基本的API. ThreadPool.QueueUserWorkItem(o => Test()); //线程池中取空闲线程执行委托(方法) Task.Run((Action)Test); //.Net 4.0以上可用 Console.WriteLine("Main Thread"); Console.ReadLine(); } static void Test() { Thread.Sleep(1000); Console.WriteLine("Hello World"); }

  

原理

  其实不管是Task,ThreadPool,本质最终都是Thread。只不过微软帮我们在简化线程控制的复杂度。

  线程池是CLR中事先定义好的一些线程。Task取的线程池,只不过在语法上,可以非常方便取返回值。

异步会提高程序的运行速度吗

  多线程会提高程序的效率,不会提高运行速度。

  这就好比这一个任务让前台花1个小时。前台完成10分钟的时候

  打电话给经理,,让他安排一个人来干30分钟(new Thread()),他干剩下的20分钟。(创建线程,需要时间,内存资源)

  或者从旁边空闲的同事中(ThreadPool 或 Task),拉一个人过来干30分钟。他干剩下的20分钟。(需要的时间少,资源本来就存在)

  从上看出,异步会让一份任务时间变长。资源消耗更多。但是可以让前台(UI线程)空闲下来,听从领导(用户)指挥。

async和await只是一个标记

  首先看个Demo,

static void Main(string[] args) { Task.Run(() => //异步开始执行 { Thread.Sleep(1000); //异步执行一些任务 Console.WriteLine("Hello World"); //异步执行完成标记 }); Thread.Sleep(1100); //主线程在执行一些任务 Console.WriteLine("Main Thread"); //主线程完成标记 Console.ReadLine(); }

  发现执行结果是:

  这个很正常。但是我们希望先执行主线程完成标记,不改动主线程和Task的任务情况下,如何处理?

使用await和async

static void Main(string[] args) { Say();                             //由于Main不能使用async标记 Console.ReadLine(); } private async static void Say() { var t = TestAsync(); Thread.Sleep(1100); //主线程在执行一些任务 Console.WriteLine("Main Thread"); //主线程完成标记 Console.WriteLine(await t); //await 主线程等待取异步返回结果 } static async Task<string> TestAsync() { return await Task.Run(() => { Thread.Sleep(1000); //异步执行一些任务 return "Hello World"; //异步执行完成标记 }); }

  1.凡是使用await关键字的方法,都必须打上async标记。

  2.async表示方法内有异步方法,await表示等待异步方法执行完,并取返回值。

  3.调用async方法,会立刻另起线程执行。await只是显示等待线程结束。

MVC中的异步Action

  既然多线程不能提高运行速度,而且每次请求Asp.net程序都是发起一个新的线程,为什么还要用多线程让其“降速”?

  为了提高网站的吞吐量。

  在MVC中,如果采用异步Action,则会像下面情况执行。

  1.请求到达IIS,IIS应用程序池分配一个worker线程用来响应请求。

  2.worker线程,执行异步操作,调用CLR线程池线程处理。

  3.释放worker线程,响应其他请求。

  4.异步操作执行完,w3wp(应用程序池进程)再次分配一个worker线程继续响应。

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/69674.html