对于 C# rest API 来说,异步是不可避免的吗?

Is async all the way inevitable for C# rest API?

我看到并阅读了很多关于 C# 中的 async-await 的页面,但仍有一些不清楚的地方。 使用像控制器 - 业务层 - 数据层这样的 3 层架构,如果你的数据层执行异步方法(因为它调用数据库或 RestAPI),你的业务层和控制器也需要异步并等待。 这是设计意图吗?

我知道 async-await 对于服务器未处理的调用很有用 CPU 例如数据库调用或 http 调用,然后你可以将当前线程交给另一个任务 return 当异步操作完成时到这个。 但是对于像我解释的那样的架构,如果你在最低层有异步方法,你最终会到处冒泡异步等待模式,它似乎在那些情况下没有用。

我一定是遗漏了一些东西或一些解释。 所以你知道我在 Whosebug 和一些 Microsoft 文档上阅读了多个线程,但仍然无法解释。

让我们反过来看这个例子。比较常规同步应用程序和内部异步但包装在同步 shell 中的应用程序。它们在外部观察者看来有何不同?

他们不会。当然,您可能知道在您的应用程序中是另一个组件阻塞了线程(例如 BLL 而不是 DAL);但是外部观察者只关心 有一个线程被阻塞,而不关心应用程序中的哪个对象或层正在做这件事。根据定义,外部观察者几乎不关心也不区分应用程序的内部实现。

应用程序不阻塞线程的唯一方法,这是异步的核心原则;是为了让等待逻辑从您的应用程序中冒出来。现在,外部观察者看到了不同之处:线程没有被阻塞,同时观察者可以去做其他事情。如果不是这种情况,那么首先就没有必要使用异步。

从本质上讲,同步代码不进行通信。你给你的员工一份工作:加热酱汁。他用微波炉。他把它放进去需要 10 秒,取出来也需要 10 秒。在微波炉加热期间,他要么站在那里什么都不做,要么离开厨房也不告诉任何人。其他人正在等待使用厨房,而他什么也没做,因此浪费了厨房的可用性,因为他从未告诉任何人他们可以在他等待微波炉时跳进去。他挡住了厨房的路,除了他选择在那里闲着之外,没有其他目的。这是一个同步工作者。

相比之下,异步工作人员会意识到自己在闲置,走出厨房让路,让其他人知道现在 space 他们可以在工作中完成自己的工作厨房。

但唯一可行的方法是,如果他真的告诉其他人他已经走出厨房,以便他们可以进去。类比的这一部分相当于让你的等待逻辑冒泡在你的应用程序之外。如果你把它放在里面,那么你就没有沟通。


还有一件事:如果您的应用程序启动了一个任务,但在任务完成时还有足够多的其他工作要做;当它最终等待(现在已经完成)任务时,它永远不会从您的应用程序中冒出来。如果线程除了等待 没有其他事情 可做,await 只会冒泡。