kotlin 为什么异常是由一个非根、非管理者协程的处理程序来处理的?

xoshrz7s  于 2022-11-16  发布在  Kotlin
关注(0)|答案(1)|浏览(106)

我用这个测试函数测试了协程的异常处理机制:

suspend fun test(){
    supervisorScope {launch(createExceptionHandler(1)) {
        coroutineScope {launch(createExceptionHandler(2)) {
            supervisorScope {launch { //SUPERVISOR WITH NO HANDLER
                coroutineScope {launch(createExceptionHandler(4)) {
                    coroutineScope {launch(createExceptionHandler(5)) {
                        throw Exception("Testing")
                    }}
                }}
            }}
        }}
    }}
}

fun createExceptionHandler(i: Int) = CoroutineExceptionHandler { _, throwable ->
    "---> exception handler #$i caught: ${throwable}".log()
}

结果:

---> exception handler #2 caught: java.lang.Exception: Testing

我期待处理程序#1捕获异常,但令我惊讶的是,是处理程序#2捕获了异常!
阅读文档时,我希望处理程序#2、#4、#5被完全忽略:
...特别是,所有子协程(在另一个Job的上下文中创建的协程)将它们的异常处理委托给它们的父协程,父协程也委托给父协程,如此类推直到根,所以安装在它们上下文中的CoroutineExceptionHandler永远不会被使用。
我所理解的是,当异常到达根目录或带有异常处理程序的 supervisorScope 时,它就会停止传播。
这个检验函数(2)似乎证实了我的信念:

suspend fun test2(){
    supervisorScope {launch(createExceptionHandler(1)) {
        supervisorScope {launch(createExceptionHandler(2)) {
            supervisorScope {launch {
                supervisorScope {launch {
                    supervisorScope {launch {
                        throw Exception("Testing")
                    }}
                }}
            }}
        }}
    }}
}

结果:

---> exception handler #2 caught: java.lang.Exception: Testing

我已经在网上阅读了许多关于异常传播和处理的指南,我在这方面相当卡住了...
任何线索都会有帮助,谢谢阅读!

dm7nw8vv

dm7nw8vv1#

在第一个例子中,supervisorScope启动了一个没有异常处理程序的协程,它实际上继承了外部作用域的异常处理程序。

相关问题