在 Kotlin 协程中 cancelChildren 应该如何工作?

How Should cancelChildren work in Kotlin Coroutines?

根据文档,cancelChildren 应该取消协程的子程序但不影响父程序("the state of this job itself is not affected.")但是如果我有像

这样的代码
    val outer = launch {
    try {
        launch (coroutineContext) {
            try {
                // work here
            } catch (ex: Exception) {
                println("In inner catch")
            } finally {
                println("In inner finally")
            }
        }
        delay(5000) // so the outer job is running when I cancel it
    } catch (ex: CancellationException) {
        println("In outer catch")
    } finally {
        println("In outer finally")
    }
}

delay(100) // give it  a chance to run
outer.cancelChildren()

然后我看到下面的

In inner catch
In inner finally
In outer catch
In outer finally

为什么 'outer' 作业被取消了?

这与我调用 outer.cancel 时得到的行为完全相同(但我希望如此)

您在外部协程中的 delay(5000) 是可取消的,因此受到 outer.cancelChildren() 的影响。它抛出在外部 try 中看到的 CancellationExceptioncancelChildren 函数不会取消外部作业,这可以通过在调用后检查 outer.isCancelled 来明确。

如果从代码中删除 delay 调用,它会打印预期的结果。请注意协程等待它们的 children anyway,没有必要延迟:

A parent coroutine always waits for completion of all its children. Parent does not have to explicitly track all the children it launches and it does not have to use Job.join to wait for them at the end.