Android kotlin 协程:await 可能会默默地丢弃异常

dom*_*nik 2 android kotlin kotlin-coroutines

在阅读https://developer.android.com/kotlin/coroutines时,我偶然发现了以下警告:

警告:启动和异步处理异常的方式不同。由于 async 期望在某个时刻最终调用await,因此它会保留异常并作为await 调用的一部分重新抛出它们。这意味着如果您使用await 从常规函数启动新的协程,您可能会默默地丢弃异常。这些丢弃的异常不会出现在您的崩溃指标中,也不会在 logcat 中注明。

但是,在浏览https://kotlinlang.org/docs/reference/coroutines/exception-handling.html或https://www.google返回的任何其他资源时,我无法找到这种无声丢弃行为的任何示例.com/search?q=kotlin+await+exception+handling - 相反,所有资源都表明在 async/await 块中抛出的异常将导致整个协程范围内的失败,这是正确且预期的。

恐怕我在这里遗漏了一些东西,您能否提供一个示例,其中发生这种静默异常丢弃,而 logcat 中无法注意到?

Mar*_*nik 5

您从 Kotlin 文档中引用的段落已过时。在实验阶段确实如此,如果你不是很迂腐的话,你真的可能会遇到吞咽异常。

协程的发布版本获得了一个额外的关键组件:结构化并发。当遵循不使用GlobalScope和类似的简单准则时,您的代码将自动组织,以便每个协程都有一个父级,并且有一个明确定义的范围,在该范围内所有协程必须正常或突然完成,并且该范围的所有者可以等待其完成,获取导致异常完成的异常。

在这个新学科中,launch并且async处于同一地位。如果其中一个内部抛出的异常逃逸了其顶级块,它会继续取消协程,通知父级,然后父级可以选择取消所有其他子级,以便整个作用域提前结束。

请注意,从调用中获取异常await是一种完全不同的机制。你await所接触的并不是async块本身,而是一个类型为 的独立对象Deferred,它与 Java 的相同Future,只是它await是挂起而不是块。该async块在完成时总是执行相同的操作:它Deferred使用返回值或异常来完成。您可以从传递的任何地方检索该结果Deferred,它与async协程的命运完全脱钩。