网站地图咋做,中国核工业第五建设有限公司待遇,个人网站如何在百度上做推广,网站个人备案修改成企业备案1.异步和多线程简介 2.IOCP 3.await后代码执行的线程1.异步和多线程简介 a.多线程: 像是你同时请了多个工人(线程)干活, 每个工人独立执行自己的任务, CPU需要在这些工人之间切换调度; 这是并发执行的一种实现方式b.异步: 是一种编程模式/思想, 核心是非阻塞 —— …1.异步和多线程简介2.IOCP3.await后代码执行的线程1.异步和多线程简介a.多线程:像是你同时请了多个工人(线程)干活,每个工人独立执行自己的任务,CPU需要在这些工人之间切换调度;这是并 发执行的一种实现方式 b.异步:是一种编程模式/思想,核心是非阻塞—— 当遇到耗时操作(比如:IO、网络请求)时,当前线程不会傻等,而是去 处理其他任务,等耗时操作完成后再回来处理结果;异步不一定需要创建新线程1).IO密集型 最典型的就是文件读写, 数据库操作, 网络请求等,这类操作的耗时主要花在等待外部设备(硬盘/网络)响应,而非占用 CPU;C#的异步在处理这类操作时,底层会利用操作系统的IOCP(IO完成端口)机制, 不会创建新线程usingSystem;usingSystem.IO;usingSystem.Threading.Tasks;classProgram{staticasyncTaskMain(){// 异步读取文件IO密集型stringcontentawaitReadFileAsync(test.txt);Console.WriteLine(content);}staticasyncTaskstringReadFileAsync(stringpath){// await执行时当前线程会返回线程池去处理其他任务// 文件读取完成后系统会通知CLR再从线程池取一个线程继续执行后续代码// 全程没有创建新线程只是复用了线程池的线程using(varreadernewStreamReader(path)){returnawaitreader.ReadToEndAsync();}}}2).CPU密集型 如果异步方法里执行的是CPU密集型任务(比如复杂计算),此时异步需要依赖多线程才能实现非阻塞usingSystem;usingSystem.Threading;usingSystem.Threading.Tasks;classProgram{staticvoidMain(){// new Thread新建操作系统线程不在线程池newThread((){// 打印线程ID是否线程池线程结果否Console.WriteLine($new Thread线程ID{Thread.CurrentThread.ManagedThreadId}是否线程池{Thread.CurrentThread.IsThreadPoolThread});}).Start();Console.ReadKey();}}2.IOCPIOCP就是操作系统为程序提供的一个异步I/O结果通知中心,程序把I/O请求交给操作系统后就可以去干别的事,等I/O操作 完成了,操作系统会通过这个通知中心告诉程序你的请求做完了, 来拿结果吧当你在C#中写awaitreader.ReadToEndAsync()时,底层流程是这样的 a.你的C#程序调用.NET 类库的异步方法,.NET会把读取文件这个IO请求交给Windows操作系统 b.操作系统把这个请求加入IOCP的待处理队列,然后立刻告诉你的C#程序请求已提交,你可以先回去干活了 c.当硬盘完成文件读取后,操作系统会把读取完成的结果放到IOCP的完成队列里 d..NET的CLR会监控这个IOCP完成队列,发现有完成的请求后,从线程池取一个空闲线程,继续执行await后面的代码,比 如打印文件内容 整个过程中,没有为这个IO请求创建新线程,只有IO完成后才短暂占用一个线程处理结果,这就是异步IO比多线程处理IO高 效的根本原因,而IOCP就是实现这个流程的核心机制3.await后代码执行的线程await后代码的执行线程,不是绝对由线程池决定,而是由await执行前当前线程的同步上下文决定 a.控制台:无特殊同步上下文,await后代码在线程池线程执行usingSystem;usingSystem.IO;usingSystem.Threading;usingSystem.Threading.Tasks;classProgram{staticasyncTaskMain(){// 打印主线程信息控制台主线程不是线程池线程Console.WriteLine($主线程ID{Thread.CurrentThread.ManagedThreadId}是否线程池线程{Thread.CurrentThread.IsThreadPoolThread});// 异步读取文件IO操作释放主线程stringcontentawaitReadFileAsync(test.txt);// 打印await后的线程信息此时是线程池线程Console.WriteLine($await后线程ID{Thread.CurrentThread.ManagedThreadId}是否线程池线程{Thread.CurrentThread.IsThreadPoolThread});Console.WriteLine(content);}staticasyncTaskstringReadFileAsync(stringpath){// 确保文件存在先创建一个测试文件if(!File.Exists(path))awaitFile.WriteAllTextAsync(path,测试IOCP异步读取);using(varreadernewStreamReader(path)){returnawaitreader.ReadToEndAsync();// IOCP处理的核心异步点}}}b.UI程序:WinForm/WPF,有UI同步上下文, await后代码会回到原UI主线程// 新建WinForm项目在Form1中添加一个按钮Button1usingSystem;usingSystem.IO;usingSystem.Threading;usingSystem.Windows.Forms;publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}privateasyncvoidButton1_Click(objectsender,EventArgse){// 打印UI主线程信息非线程池线程MessageBox.Show($点击按钮的线程ID{Thread.CurrentThread.ManagedThreadId}是否线程池线程{Thread.CurrentThread.IsThreadPoolThread});// 异步读取文件stringcontentawaitFile.ReadAllTextAsync(test.txt);// 打印await后的线程信息还是原UI主线程MessageBox.Show($await后线程ID{Thread.CurrentThread.ManagedThreadId}是否线程池线程{Thread.CurrentThread.IsThreadPoolThread});// 直接更新UI控件无跨线程异常因为回到了UI线程label1.Textcontent;}}c.unity中await后代码会回到主线程usingUnityEngine;usingUnityEngine.UI;usingSystem.Threading.Tasks;publicclassAsyncLoadAwaitExample:MonoBehaviour{publicTexttipText;privateasyncvoidStart(){Debug.Log($Start方法线程ID{System.Threading.Thread.CurrentThread.ManagedThreadId});// 异步加载资源await后自动回主线程varresourceRequestResources.LoadAsyncSprite(Images/player);awaitresourceRequest;// 打印await后的线程ID和主线程一致Debug.Log($await后线程ID{System.Threading.Thread.CurrentThread.ManagedThreadId});// 直接操作UISpritesprite(Sprite)resourceRequest.asset;tipText.textAwait加载完成;}}