gpt4 book ai didi

kotlin - 为什么在协程 block 内直接调用 `async`不继承SupervisorJob?

转载 作者:行者123 更新时间:2023-12-02 12:41:13 26 4
gpt4 key购买 nike

给定以下代码片段:

片段[1]

val job = SupervisorJob()
val scope = CoroutineScope(Dispatchers.IO + job)
scope.launch {
try {
scope.async {
throw RuntimeException("Oops!")
}.await()
} catch(e: Exception) {
// Handle exception
}
}

和片段[2]

val job = SupervisorJob()
val scope = CoroutineScope(Dispatchers.IO + job)
scope.launch {
try {
async {
throw RuntimeException("Oops!")
}.await()
} catch(e: Exception) {
// Handle exception
}
}

第一个有效,第二个片段崩溃。一般的解释是,在第一种情况下,asyncscope 中继承了SupervisorJob,而在第二种情况下则没有。

我的问题是,如果 asyncCoroutineScope 的扩展函数,为什么在第二种情况下(崩溃)它不继承 SupervisorJob以同样的方式?

最佳答案

在您的第一个代码段中,因为您显式地覆盖了 launch 构建器建立的范围,所以它与您内部的 async block 之间没有父子关系

这是编写第一个片段的等效方法:

val deferred = scope.async {
throw RuntimeException()
}

scope.launch {
try {
deferred.await()
} catch(e: Exception) {
}
}

async 协程因异常而失败。它的父级是 SupervisorJob,它会忽略失败。 launch 协程调用 Deferred.await(),这会引发异常。您捕获了异常,没有任何失败。

您的第二个片段可以重写如下:

scope.launch {
val innerScope = this

innerScope.async {
throw RuntimeException()
}
}

在这里您可以明确地看到 async block 继承了哪个范围。它不是带有 SupervisorJob 的顶级,而是 launch 创建的内部。当 async 协程失败时,父作业对其作出 react ,首先取消所有其他子作业(在本例中为无),然后取消自身。 deferred.await() 语句在这里没有任何区别,这就是我删除它的原因。 launch 协程将自动等待所有子协程完成。

关于kotlin - 为什么在协程 block 内直接调用 `async`不继承SupervisorJob?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59097978/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com