它使编写异步代码变得非常容易。正如您在自己的问题中指出的那样,它看起来像是编写同步变体 - 但实际上是异步的。
要理解这一点,您需要真正了解什么是异步和同步。意思很简单-同步意味着按顺序,一个接一个。异步意味着不按顺序。但这并不是整个图片-这两个词本身几乎没有用处,它们的大部分含义都来自上下文。您需要问:相对于什么同步,确切地说?
假设您有一个需要读取文件的Winforms应用程序。在按钮单击中,您执行File.ReadAllText
,并将结果放入某些文本框-所有都很好。 I / O操作相对于您的UI是同步的-当您等待I / O操作完成时,UI无法执行任何操作。现在,客户开始抱怨UI在读取文件时似乎挂起了数秒钟-而Windows标记该应用程序为“未响应”。因此,您决定将文件读取委托给后台工作者-例如,使用BackgroundWorker
或Thread
。现在,相对于您的UI,I / O操作是异步的,每个人都很高兴-您所要做的就是提取工作并在其自己的线程中运行它,耶。
现在,这实际上是完全可以的-只要您一次只进行一个此类异步操作。但是,这确实意味着您必须明确定义UI线程边界-您需要处理适当的同步。当然,在Winforms中,这非常简单,因为您可以使用Invoke
将UI工作调度回UI线程-但是如果您需要重复与UI交互,同时进行后台工作怎么办?当然,如果您只想持续发布结果,则可以使用BackgroundWorker
的ReportProgress
-但是如果您还想处理用户输入怎么办?
await
的美妙之处在于,您可以轻松管理何时在后台线程上以及何时在同步上下文(例如Windows窗体UI线程):
string line;
while ((line = await streamReader.ReadLineAsync()) != null)
{
if (line.StartsWith("ERROR:")) tbxLog.AppendLine(line);
if (line.StartsWith("CRITICAL:"))
{
if (MessageBox.Show(line + "\r\n" + "Do you want to continue?",
"Critical error", MessageBoxButtons.YesNo) == DialogResult.No)
{
return;
}
}
await httpClient.PostAsync(...);
}
这很棒 - 实际上,您基本上像往常一样编写同步代码,但与 UI 线程相比仍然是异步的。错误处理与任何同步代码完全相同-使用、try-finally 和 friends 都非常好用。
好吧,你不需要在这里和那里洒些 BeginInvoke,有什么大不了的?真正的大问题是,在您不费吹灰之力的情况下,实际上开始为所有这些 I/O 操作使用真正的异步 API。事实上,就操作系统而言,没有真正的同步 I/O 操作-当您执行“同步”File.ReadAllText时,操作系统只是发布了一个异步 I/O 请求,然后阻塞您的线程,直到响应返回。显然,此期间该线程无所事事-它仍然使用系统资源,为调度程序添加了微小的工作等等。
再次说明,在典型的客户端应用程序中,这并不是什么大问题。用户不关心您是否有一个线程或两个线程-差别并不是很大。但是服务器完全是另一回事;在典型的客户端中,您只有同时进行一两个 I/O 操作,而您希望您的服务器处理数千个!在典型的 32 位系统上,您可以通过使用默认堆栈大小在进程中仅容纳约 2000 个线程-不是因为物理内存要求,而仅仅是通过耗尽虚拟地址空间。64 位进程没有那么受限制,但仍然存在一个问题,即启动新线程和销毁它们相当昂贵,并且您现在正在添加相当多的工作以使操作系统线程调度器保持这些线程等待。
但是基于 await 的代码没有这个问题。只有在执行 CPU 工作时才使用线程-等待 I/O 操作完成不是 CPU 工作。因此,您发出异步 I/O 请求,然后将线程返回到线程池。响应到达时,将从线程池中取出另一个线程。突然之间,您的服务器只使用几个线程(通常每个 CPU 核心约两个)。内存要求更低,多线程开销显着降低,总吞吐量也大大提高。
因此,在客户端应用程序中,await 只是一种方便的事情。在任何较大的服务器应用程序中,它是必需品-因为突然间您的“启动新线程”方法根本无法扩展。使用 await 的替代方案是所有那些老式的异步 API,它们处理与同步代码完全不同的内容,处理错误非常繁琐和棘手。
await
关键字你会如何编写相同的异步代码...那将更难以阅读(和编写)。你的例子在功能上是等效的,但第一个不会阻塞线程只是为了等待I/O。 - Lucas Trzesniewskiasync
介绍,然后再阅读我的MSDN异步最佳实践文章和官方TAP文档。如果你想深入了解,Jon Skeet的eduasync将向你展示比你所需知道的更多内容。 - Stephen Cleary