使用C#,为什么在同步版本可用时等待Async方法?

0 c# async-await

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

using (XmlReader reader = XmlReader.Create(stream, settings))
{
    while (await reader.ReadAsync())
    {
        // Do something
    }
}
Run Code Online (Sandbox Code Playgroud)

比这更好......

using (XmlReader reader = XmlReader.Create(stream, settings))
{
    while (reader.Read())
    {
        // Do something
    }
}
Run Code Online (Sandbox Code Playgroud)

换句话说,如果您在等待... Async方法做其事情时,无意做其他事情,为什么要使用它?如果同步方法可用,为什么不使用它?

此Async示例取自:https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmlreader?view = networkwork4.7.1

编辑:在阅读了被认为是重复的问题和答案后,他们没有帮助.我特意询问了与被调用的异步方法在同一行上等待的简单情况.我的问题已在下面得到解答.谢谢你们!

Yan*_*eus 6

从根本上说,使用异步方法调用不会阻塞线程,这是任何机器上的有限资源.假设您有一个方法调用,由于网络延迟,繁重的数据库工作负载等,可能需要3秒钟才能完成.如果您同步调用此方法,您的线程实际上就坐在那里等待结果返回,其余部分无视你的申请.

异步方法调用(或async/await,因为它通俗地知道和调用)是非阻塞的.因此,如果你的执行线程遇到一个方法,表明它可以被等待,它将(并且我在这里大大过分简化了)将标志放在沙子中并告诉系统只做那件事并在你'时给我打电话'重做.

现在你可能在想,"但是等等!这是不是意味着另一个线程必须完成当前线程刚委派的工作?!" 你是对的.

这就是前景和后台线程的概念所在.前台线程的一个例子就像处理控制器中的Web API调用的线程,或UI渲染线程.

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

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

当人们说它使应用程序更高效时,通过使其更加并发,但不一定更快,这是事实.

为了解决Mihir Dave留下的评论:

滥用异步/等待将包括尝试将其应用于纯计算方法(例如,没有I/O,纯粹是CPU绑定).那时你增加了很多复杂性和开销,没有任何好处.另一个不好的应用程序并不是从上到下,如果你开始尝试"同步"异步方法,或者"异步"同步方法,死锁的风险会急剧增加.后者在使用过时的API时很常见,这可能不会暴露异步方法.

关于async/await read的广泛阅读将是Q:why-shouldnt-all-functions-be-async-by-default