对只返回Task的异步方法使用wait



在我的ASP中。NET核心应用程序我有几十个以形式创建的方法

public async Task DoStuff() 
{ 
// ...
}

所以,没有返回类型。

后来,我意识到我不小心忘记了在调用方方法中包括wait,因为async"僵尸病毒"还没有传播那么远,所以这些方法显然没有async关键字。

在执行死刑期间,没有任何不必要的后果。

问题是,当这种事情发生时,Visual Studio也不会生成警告消息,我在问自己,在这种情况下,是否真的存在忽略等待的危险?我知道等待应该自然地应用于每个异步方法,但当调用者实际上并没有返回值可供使用时,我并不真正理解这背后的原因。也许是一些捕捉异常的东西?

我还没有找到任何明确的答案,因为一般的说法是"简单地包括等待"。信不信由你,这种异步/等待的东西,我相对来说是个新手,不时地反复折磨我。

在执行过程中,没有任何不必要的后果。

我不同意。生成的代码是危险的。ASP。NET pre-Core能够检测到类似的情况并抛出异常("异步模块或处理程序在异步操作仍然挂起时完成")。由于技术原因,ASP。NET Core无法检测到这种情况,因此您不会得到";"安全网";例外,但情况本身仍然同样糟糕。

问题是,当这种事情发生时,Visual Studio也不会生成警告消息

您没有得到CS4014("因为没有等待此调用,所以在调用完成之前将继续执行当前方法。请考虑将等待运算符应用于调用的结果。"?

在这种情况下,是否真的存在放弃等待的危险?我知道等待应该自然地应用于每个异步方法,但当调用者实际上并没有返回值可供使用时,我并不真正理解这背后的原因。也许是一些捕捉异常的东西?

是的,存在危险。Task(即使没有结果类型)用于两件事:用于调用者知道操作何时完成,以及用于调用者检测该操作的异常。

因此,一个问题是,例外被默默地吞噬了。更具体地说,async方法的异常由async状态机捕获,并放置在返回的Task上,然后忽略它。

如果我自己处理上述方法中的异常(那些没有正确等待的异常),我们能说一切都很好吗?

否,因为另一个问题仍然存在:调用方不知道异步操作何时完成。这一点在ASP中尤为重要。NET,因为在操作完成之前不应发送结果。任何类型的";火与遗忘;ASP上的代码。NET在请求/响应生存期之外生存;即它的请求外部代码。

我在博客中详细介绍了为什么请求外部代码是危险的。总之,您的ASP。NET处理程序可能完成得太快,在这种情况下,请求外部代码可能会得到";丢失";。至少,它所做的一切都不会在发送响应时完成;在定期关闭(例如,滚动升级)的情况下,可能根本无法完成

最新更新