为什么 runBlocking 不能接受 CoroutineExceptionHandler ?

Ely*_*lye 5 kotlin kotlin-coroutines

当我有

    @Test
    fun test() {
        val handler = CoroutineExceptionHandler { _, exception ->
            println("CoroutineExceptionHandler got $exception")
        }

        GlobalScope.launch(handler) {
            throw IllegalAccessException("Just testing")
        }

        Thread.sleep(300)
    }
Run Code Online (Sandbox Code Playgroud)

打印效果很好

CoroutineExceptionHandler got java.lang.IllegalAccessException: Just testing

Process finished with exit code 0
Run Code Online (Sandbox Code Playgroud)

即使我替换GlobalScopeMainScope(),一切仍然工作正常。

但是,如果我runBlocking按如下方式使用,

    @Test
    fun test() {
        val handler = CoroutineExceptionHandler { _, exception ->
            println("CoroutineExceptionHandler got $exception")
        }

        runBlocking(handler) {
            throw IllegalAccessException("Just testing")
        }

        Thread.sleep(300)
    }
Run Code Online (Sandbox Code Playgroud)

它崩溃了

java.lang.IllegalAccessException: Just testing

    at com.example.coroutinerevise.CoroutineExperiment$test$1.invokeSuspend(CoroutineExperiment.kt:32)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
    at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
    at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
    at com.example.coroutinerevise.CoroutineExperiment.test(CoroutineExperiment.kt:31)
Run Code Online (Sandbox Code Playgroud)

为什么 runBlocking 不能CoroutineExceptionHandler触发给定的?

Sta*_*chu 2

根据
https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/exception-handling.md#cancellation-and-exceptions不支持它

如果协程遇到 CancellationException 以外的异常,它会取消带有该异常的父级。此行为无法重写,用于为结构化并发提供稳定的协程层次结构。CoroutineExceptionHandler 实现不用于子协程。

runBlocking 创建一个子协程
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html

运行一个新的协程并中断地阻塞当前线程,直到其完成。

像这样的东西会起作用,但有点丑陋

    @Test
    fun test() {
        val handler = CoroutineExceptionHandler { _, exception ->
            println("CoroutineExceptionHandler got $exception")
        }
        try{
            runBlocking {
                throw InterruptedException("Just testing")
            }
        } catch(e:Exception){
            handler.handleException(GlobalScope.coroutineContext,e)
        }
        Thread.sleep(300)
    }
Run Code Online (Sandbox Code Playgroud)