在我的ASP.NET核心应用程序中,我用以下形式创建了几个方法
public async Task DoStuff()
{
// ...
}
所以,没有返回类型。
后来,我意识到,我意外地忘记了在调用者方法中到处包含这些方法的等待(这些方法显然没有异步关键字,因为异步“僵尸病毒”还没有传播到那么远)。
在执行过程中,没有任何不必要的后果。
问题是,当这种事情发生时,Visual也生成没有警告消息--我在问自己,在这种情况下是否存在释放等待的危险?我知道等待应该自然地应用于每个异步方法,但当调用者实际上没有可使用的返回值时,我并不真正理解背后的原因。也许有什么能抓住例外的东西?
我没有找到任何明确的答案,因为一般的说法是‘简单地包括等待’。不管你信不信,这个异步/等待的东西,我相对来说还是比较新的,不时地反复咬我一口。
发布于 2021-02-07 04:57:08
在执行过程中,没有任何不必要的后果。
我不同意。产生的代码是危险的。ASP.NET pre能够检测到类似的情况并抛出一个异常(“异步操作仍未完成时完成的异步模块或处理程序”)。由于技术原因,ASP.NET核心无法检测到这种情况,因此您不会得到“安全网”异常,但情况本身仍然同样糟糕。
问题是,在发生这种情况时,Visual也不会生成警告消息。
你没有得到CS4014 (“因为没有等待此调用,当前方法的执行将在调用完成之前继续。请考虑将等待操作符应用于调用的结果”)。
在这样的情况下,是否存在脱离等待的危险呢?我知道等待应该自然地应用于每个异步方法,但当调用者实际上没有可使用的返回值时,我并不真正理解背后的原因。也许有什么能抓住例外的东西?
是的,有危险。Task
(即使没有结果类型)用于两种情况:调用者知道操作何时完成,调用者检测该操作的异常。
因此,有一个问题是,例外会被默默地吞没。更具体地说,async
方法的异常由async
状态机捕获并放置在返回的Task
上,然后被忽略。
如果我处理这些方法本身的例外情况(那些未被妥善等待的),我们是否可以说一切都很好?
不,因为另一个问题仍然存在:调用方不知道异步操作何时完成。在ASP.NET中知道这一点特别重要,因为在操作完成之前不应该发送结果。ASP.NET上的任何类型的“触发和遗忘”代码都存在于请求/响应生存期之外;也就是说,它是请求--外部代码。
我在博客中详细介绍了为什么请求-外部代码是危险的?。总之,您的ASP.NET处理程序可能完成得太快,在这种情况下,请求-外部代码可能会“丢失”。至少,在发送响应时,它所做的任何事情都不会完成;在定期关闭的情况下(例如,滚动升级),它可能根本无法完成。
https://stackoverflow.com/questions/66087702
复制