2026/4/16 9:10:03
网站建设
项目流程
免费申请试用网站,广告设计与制作专业怎么样,去掉网址中的wordpress,wordpress首页文章图片1.上下文
2.Async和Await简介
3.Await后续代码在哪个线程执行
4.Await 和同步上下文
5.Await究竟干了什么1.上下文
想象一下: 你在不同的场合, 同样是我饿了, 意思完全不同a.在家说我饿了 - 妈妈给你做饭b.在朋友家说我饿了 - 朋友…1.上下文2.Async和Await简介3.Await后续代码在哪个线程执行4.Await 和同步上下文5.Await究竟干了什么1.上下文想象一下:你在不同的场合,同样是我饿了,意思完全不同 a.在家说我饿了-妈妈给你做饭 b.在朋友家说我饿了-朋友给你零食 同样一句我饿了,因为说的时候环境不同,结果完全不同编程中的上下文就是当前代码能有的所有东西(变量,方法,类,资源,环境信息)的集合,就 像你在厨房,上下文就是厨房里的工具(刀,锅,食材),你能做饭publicclassExample{privatestringname全局名字;// 这是类的上下文成员变量publicvoidMethod1(){stringname局部名字;// 这是方法的上下文局部变量Console.WriteLine(name);// 输出“局部名字”// 因为当前方法上下文中有name就先用它}publicvoidMethod2(){Console.WriteLine(name);// 输出“全局名字”// 方法上下文没有name就用类的上下文中的name}}同步上下文在异步操作后,默认会回到原来的上下文// UI程序中控制回到UI线程执行privateasyncvoidButton_Click(objectsender,EventArgse){// 异步操作前UI线程上下文awaitTask.Delay(1000);// 异步操作后默认会回到原来的上下文UI线程label.Text完成;// 安全访问UI控件}// 指定不捕获上下文提高性能awaitTask.Delay(1000).ConfigureAwait(false);// 这里不会回到UI线程上下文2.Async和Await简介async与await用来简化异步编程,让异步代码像同步代码一样,易于理解 a.async关键字用于修饰一个方法,表示该方法是异步的;异步方法的返回类型通常是Task,TaskTb.异步方法内部,可以使用await关键字来等待一个异步操作(Task),而不会阻塞当前线程 c.使用await关键字的方法必须用async修饰// 1. 声明异步方法在方法前加 asyncpublicasyncTaskstring下载网页(){// 2. 使用 await 等待异步操作完成string内容await网络下载方法();// 3. await 后面的代码会等待但不会阻塞线程Console.WriteLine(下载完成);return内容;// 自动包装成 Taskstring}3.Await后续代码在哪个线程执行a.当初始的await被调用时,异步函数内部的代码仍在与调用线程相同的线程上运行 b.后续的await延续内容可能在不同的线程池中执行,取决于线程池4.Await 和同步上下文在C#异步编程中,await关键字用于挂起当前方法,直到等待的异步操作完成;当异步操作完成 后,方法会尝试恢复执行同步上下文(SynchronizationContext)是一个抽象,它代表了一个线程的上下文环境;在 Windows Forms、WPF、ASP.NET等应用程序模型中,都有一个特定的同步上下文,它通常与 UI线程相关联,用于确保代码在正确的线程上执行(如:UI控件的更新必须在UI线程上进行)当我们使用await时,默认情况下,await会捕获当前的同步上下文,并在该同步上下文中恢复 执行;这意味着,如果在UI线程上使用await,那么await之后的代码将会在UI线程上执行,这样我们就可以安全地更新UI控件ConfigureAwait(false)来告诉await不需要捕获原始同步上下文,而是在线程池上下文中恢 复执行privateasyncvoidbutton1_Click(objectsender,EventArgse){// 这里在UI线程上执行awaitSomeAsyncMethod();// 这里也会在UI线程上执行所以可以安全更新UIlabel1.TextDone;}5.Await究竟干了什么当我们使用async和await时,c#编译器将异步方法转换成一个状态机;状态机将异步方法分成 了多个步骤,每一个await都是一个状态;当遇到await时,如果等待的任务尚未完成,状态机 会将方法挂起(返回),并注册一个续延(continuation),当任务完成后,再调用续延来恢复 方法的执行(从上次暂停的地方继续)1).原始代码asyncTask 示例方法(){Console.WriteLine(开始);inta10;stringresultawait网络请求();// 第一个awaitaa5;Console.WriteLine($结果:{result}, a{a});awaitTask.Delay(1000);// 第二个awaitConsole.WriteLine(完成);}2).编译器把它变成状态机// 伪代码展示状态机原理class状态机{int状态0;// 0刚开始1第一个await后2第二个await后inta;stringresult;void继续执行(){switch(状态){case0:// 第一次执行Console.WriteLine(开始);a10;发起的网络请求开始网络请求();状态1;// 挂起等网络请求完成break;case1:// 网络请求完成后继续result获取网络请求结果();aa5;Console.WriteLine($结果:{result}, a{a});开始延迟();状态2;// 挂起等延迟完成break;case2:// 延迟完成后继续Console.WriteLine(完成);break;}}}