为什么将父coroutineContext.job设置为Job()不会导致子进程被取消?

问题描述 投票:0回答:1

在下面的代码中,我使用 launch 在scope1中构建了一个协程。我将其作业设置为 Job 的实例,因此任何子作业的取消都会导致父作业被取消。

我使用了

awaitAll
,根据文档,“一旦任何延迟失败,这个awaitAll就会立即失败。”


val scope1 = CoroutineScope(Dispatchers.Default)
val result = IntArray(4)

fun main() = runBlocking {
    val parentJob = scope1.launch(Job()) {
        val childJobList = (1..4).map { i ->
            async {
                delay(i.toLong() * 1000.toLong())
                if (i == 2) {
                    cancel()
                }
                yield()
                println("async $i is done")
                result[i - 1] = i
            }
        }
        try {
            childJobList.awaitAll()
            println("Child job completed successfully")
        } catch (e: Exception) {
            println("Caught exception in parent: ${e.message}")
        }
    }

    parentJob.join()
    println("Parent job completed; result = ${result.contentToString()}")
}

然而,事实似乎并非如此。运行代码会产生以下输出:

async 1 is done
Caught exception in parent: DeferredCoroutine was cancelled
async 3 is done
async 4 is done
Parent job completed; result = [1, 0, 3, 4]

有人可以帮忙解释一下为什么会出现这种情况吗?

kotlin kotlin-coroutines coroutine
1个回答
0
投票

我不太确定哪个部分让您感到困惑。

awaitAll
显然失败了,我们可以从“在父级中捕获异常:DeferredCoroutine 被取消”日志中看到。您捕获了异常,因此父协程没有失败。

关于这个:

任何孩子的取消都会导致家长的工作被取消。

取消不会传播给父母,只有“真正的”失败才会传播给父母。我们可以在文档中找到对此的多次提及,例如:

如果协程遇到 CancellationException 以外的异常,它会取消其父级并返回该异常。

https://kotlinlang.org/docs/exception-handling.html#cancellation-and-exceptions

© www.soinside.com 2019 - 2024. All rights reserved.