.NET 中 async 和 await
2021/4/25 10:25:46
本文主要是介绍.NET 中 async 和 await,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
C# 中的 Async 和 Await 关键字是异步编程的核心。使用这两个关键字可以轻松创建异步方法。使用 async
关键字定义的异步方法简称“异步方法”。
异步编程
并发的一种形式,它采用furture模式或回调(callback)机制,以避免产生不必要的线程。.Net中future的类型有 Task
和 Task
。
异步编程的核心理念是异步操作:
启动了的操作将会在一段时间后完成。
这个操作正在执行时,但不会阻塞原来的线程。
启动了这个操作的线程后,可以继续执行其它任务。
当操作完成时,它会通知它的future,或者调用回调函数,以便让程序知道操作已经结束。
异步的好处
对于面向终端用户的GUI程序,异步可以提高响应能力。
对于服务器应用:异步编程实现了可扩展。
服务器可以利用线程池填满其可扩展性,使用异步编程后,可扩展性通常可以提供一个数量级,可以最大程度的压榨服务器性能,提高处理能力。
async
使用 async
修饰符可以将方法、lambda表达式或匿名方法指定为异步。
async
的主要目的是,使方法内的await关键字生效。
//等待异步完成再执行后边的操作,但是整个方法不会阻塞 var result = await DoSomethingAsync(); output.Result = result;
如果使用了 Async
最好一直使用它
await
async
标记的异步方法,可以使用 await
来指定暂定点。await
运算符通知编译器异步方法:在等待的异步过程完成后才能继续通过该点。同时,会将控制权返回至异步方法的调用方。
async
方法在开始时以同步的方式执行。在 async
方法内部,await
关键字对他的参数(一个异步任务)执行一个异步等待。它首先检查操作是否已经完成,如果完成了,就继续运行(同步方法)。否则,他会暂停 async
方法,并返回,将控制权交给调用方,留下一个 未完成的 Task
。一段时间后,操作完成,async
方法再恢复运行。
用 await
语句等待一个任务完成,当该方法在 await
处暂停时,就可以捕捉上下文(context)。如果当前SynchronizationContext
不为空,这个上下文就是当前SynchronizationContext
。如果当前SynchronizationContext
为空,则这个上下文为当前TaskScheduler
。该方法会在这个上下文中继续运行。
//此时await会捕获当前上下文 await DoSomethingAsync(); //.... //这里会试图用上边捕获的上下文继续执行
await DoSomethingAsync().ConfigureAwait(false); //.... 这里开始在新的线程中运行
ConfigureAwait
配置 Task
的 awaiter
,将延续任务封装回原始上下文,则为True
,否则为 False
。
详情可查阅ConfigureAwait(false)资料,这里暂时不做赘述。可阅读以下文章
- 原文ConfigureAwait FAQ https://devblogs.microsoft.com/dotnet/configureawait-faq/
- 译文理解C#中的ConfigureAwaithttps://www.cnblogs.com/xiaoxiaotank/p/13529413.html
异步方法异常:
异步方法异常时会返回在 Task 对象中,并将这个 Task 对象的状态改变为“已完成”。当 await 调用该 Task 对象时,await 会获得并(重新)抛出该异常,并保留原始的栈轨迹。
注意:
异步方法避免使用 Task.Wait
和 Task
,因为他们会导致死锁。
示例:
public async Task<int> GetUrlContentLengthAsync() { var client = new HttpClient(); //异步执行请求,立即返回一个Task Task<string> getStringTask = client.GetStringAsync("https://docs.microsoft.com/dotnet"); //由于异步方法未执行等待,所以可以继续执行不依赖异步返回结果的同步方法 DoIndependentWork(); //挂起任务进度,并将控制权交割GetUrlContentLengthAsync方法的调用方,并返回一个Task //该任务表示将返回下载字符串长度的一个承诺 //然后调用方会继续执行,执行不依赖于GetUrlContentLengthAsync返回结果的其它工作,否则就等待。 string contents = await getStringTask; return contents.Length; } void DoIndependentWork() { Console.WriteLine("Working..."); }
await
运算符会暂停 GetUrlContentLengthAsync
方法:
- 在
getStringTask
完成之前,GetUrlContentLengthAsync
无法继续。 - 同时,控件返回至
GetUrlContentLengthAsync
的调用方。 - 当
getStringTask
完成时,控件将在此继续。 - 然后,
await
会从getStringTask
检索string
结果
如果 DoIndependentWork
依赖于异步执行的结果,则在等待 getStringTask
返回结果期间不能进行任何工作。需要改成以下写法。
string getStringTask = await client.GetStringAsync("https://docs.microsoft.com/dotnet");
构成异步方法的条件:
- 方法签名要包含
async
修饰符。 - 按照约定,异步方法的名称以“Async”后缀结尾。
- 返回类型为以下类型之一
- 如果你的方法有返回值,则返回 Task
- 如果你的方法没有返回值,则返回 Task 类型
- 方法中至少要包含一个 await 表达式,该表达式标记一个点,在该点上,直到等待的异步操作完成方法才能继续。同时,并且将控制权返回到方法的调用方。
返回类型
await 运算符的操作数通常是以下几种.NET类型:Task、Task
总结
- 异步可以提高响应能力。
- 异步不会阻塞线程
- 使用
async
来标记异步方法 - 使用
await
来指定暂停点,挂起其进度,在等待的异步过程完成后才能继续通过该点。同时,会将控制权返回至异步方法的调用方,调用方可以继续执行不依赖于异步返回结果的其它工作。 - 如果使用了
Async
最好一直使用它 - 异步方法避免使用
Task.Wait
和Task
,因为他们会导致死锁。
这篇关于.NET 中 async 和 await的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-03-01沐雪多租宝商城源码从.NetCore3.1升级到.Net6的步骤
- 2024-11-18微软研究:RAG系统的四个层次提升理解与回答能力
- 2024-11-15C#中怎么从PEM格式的证书中提取公钥?-icode9专业技术文章分享
- 2024-11-14云架构设计——如何用diagrams.net绘制专业的AWS架构图?
- 2024-05-08首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!
- 2024-03-30C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
- 2024-03-29c# datetime tryparse
- 2024-02-21list find index c#
- 2024-01-24convert toint32 c#
- 2024-01-24Advanced .Net Debugging 1:你必须知道的调试工具