使用C#,当同步版本可用时,为什么还要等待异步方法呢?

使用C#,当同步版本可用时,为什么还要等待异步方法呢?,c#,async-await,C#,Async Await,有很多关于wait和async的解释,现在可以在C#中找到;但似乎没有什么能解释为什么 using (XmlReader reader = XmlReader.Create(stream, settings)) { while (await reader.ReadAsync()) { // Do something } } 比这个好 using (XmlReader reader = XmlReader.Create(stream, settings))

有很多关于wait和async的解释,现在可以在C#中找到;但似乎没有什么能解释为什么

using (XmlReader reader = XmlReader.Create(stream, settings))
{
    while (await reader.ReadAsync())
    {
        // Do something
    }
}
比这个好

using (XmlReader reader = XmlReader.Create(stream, settings))
{
    while (reader.Read())
    {
        // Do something
    }
}
换句话说,如果您在等待…异步方法完成它的工作时不打算做其他事情,那么为什么要全部使用它呢?如果同步方法可用,为什么不直接使用呢

此异步示例取自:


编辑:在阅读了被认为是重复的问题和答案后,他们没有提供帮助。我特别询问了一个简单的例子,即将wait与正在调用的异步方法放在同一行上。我的问题已经在下面得到了回答。谢谢大家!

它将释放线程来做其他事情(可能),而不是旋转并等待IO完成。对于web应用程序,这有助于通过使用这些线程处理更多请求来扩展应用程序。对于UI应用程序,它允许主(UI)线程保持应用程序对用户输入的响应


您可以在.NET中阅读有关异步好处的更多信息。

这取决于您的用例。使用
wait
将释放当前线程以执行其他操作。如果此线程是桌面应用程序中的UI线程,则必须释放它以处理UI。如果您在Web服务器上,您将需要释放线程来处理其他请求,线程不是空闲的,它们占用1MB的内存作为堆栈空间


如果您不关心调用同步版本的任何场景,那么从根本上说,使用异步方法调用不会阻塞线程,因为线程在任何机器上都是有限的资源。假设您有一个方法调用,由于网络延迟、繁重的数据库工作负载等原因,可能需要3秒钟才能完成。如果您同步调用此方法,您的线程实际上会坐在那里等待返回结果,而应用程序的其余部分则不会注意

异步方法调用(或async/await,通俗地说是已知和调用的)是非阻塞的。因此,如果您的执行线程遇到一个表示可以等待它的方法,它会(我在这里过于简单化了)在沙地上放置一个标志,告诉系统只做这件事,完成后给我一个调用

现在你可能会想,“但是等等!这不意味着另一个线程必须完成当前线程刚刚委派的任务吗?!”你是对的

这就是前台和后台线程的概念。前台线程的一个示例类似于在控制器中处理web API调用的线程,或者UI呈现线程

阻塞这些线程是有害的,有几个原因,在API线程的情况下,您基本上缩小了在任何给定时间每秒可以处理多少请求的窗口。在UI的情况下,它可能会在后台工作时暂停渲染几秒钟

那么,一般来说,积极和消极因素是什么呢?在使用async/await时,您可以更均匀地分配线程工作负载,这会损害内存开销(必须记住沙子中所有标志的位置,并跟踪进程何时可以继续)

当人们说它提高了应用程序的性能时,这是真的,因为它提高了并发性,但不一定更快

针对Mihir Dave留下的评论:

滥用async/await可能包括尝试将其应用于纯计算方法(例如,无I/O,纯CPU限制)。在这一点上,您增加了很多复杂性和开销,但没有任何好处。另一个糟糕的应用程序不是自上而下地采用它,如果您开始尝试“同步”异步方法或“异步”同步方法,死锁的风险会显著增加。后者在使用过时的API时非常常见,这些API可能不会公开异步方法

关于async/await read的广泛阅读将是

您写道:

如果你在等待的时候不打算做其他事情

也许在你等待的时候,你的程序无意做其他的事情,但是你的来电者可能想做

如果您为某个任务调用wait,而该任务尚未完成,那么线程将进入调用堆栈,查看调用方是否正在等待任务,如果没有,线程将开始执行语句,直到他必须等待为止。线程再次进入调用堆栈


因此,即使您不必做一些有用的事情,如果您认为调用者很有可能想做一些事情,而不是等到您准备好了再做,那么无论何时您可以选择调用异步函数,最好使您的函数异步。如果您认为您的类将被广泛使用,请考虑创建一个异步和非异步版本

如果使用任何基于UI的平台,则同步方法阻止UI线程。(如果是WPF/Win表单,则冻结UI)。这可能会导致操作系统将程序标记为无响应。因此,使用异步方法,用户界面将得到响应。异步方法调用是异步的,因为它正在等待IO。如果您在移动或桌面上工作,则同步线程会阻塞用户界面线程,而在服务器上使用异步方法是一个巨大的成功。服务器可以释放并重用当前线程,等待异步方法调用完成,该调用使用一个通知信号。异步方法(当方法绑定IO时)可以显著提高服务器上的可伸缩性。回答不错。我有一个问题,如果有人误用async/wait,他们是否可能最终会失去性能?@MihirDave在对我的回答进行编辑时回答说,因为这比允许的评论要长。你说“现在你可能正在思考”,但等等!这难道不意味着另一个线程必须完成当前线程刚刚委派的任务吗?!“你是对的”,但事实并非总是如此。在里面