【问题标题】:kotlin coroutines, how does launch handles exceptionkotlin协程,launch如何处理异常
【发布时间】:2019-07-13 18:59:58
【问题描述】:

与

fun main(args: Array<String>) {
runBlocking {

        withTimeout(1300L) {
            repeat(1000) { i ->
                    println("I'm sleeping $i ...")
                delay(500L)
            }
        }

}
}

异常崩溃:

I'm sleeping 0 ...
I'm sleeping 1 ...
I'm sleeping 2 ...
Exception in thread "main" kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 1300 ms
 at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException (Timeout.kt:128) 
 at kotlinx.coroutines.TimeoutCoroutine.run (Timeout.kt:94) 
 at kotlinx.coroutines.EventLoopImplBase$DelayedRunnableTask.run (EventLoop.kt:307) 
 at kotlinx.coroutines.EventLoopImplBase.processNextEvent (EventLoop.kt:116) 
 at kotlinx.coroutines.DefaultExecutor.run (DefaultExecutor.kt:68) 
 at java.lang.Thread.run (Thread.java:745)

但块在launch内

fun main(args: Array<String>) {
runBlocking {
    launch {//<===
        withTimeout(1300L) {
            repeat(1000) { i ->
                    println("I'm sleeping $i ...")
                delay(500L)
            }
        }
    }//<===
}
}

那么超时也不例外:

I'm sleeping 0 ...
I'm sleeping 1 ...
I'm sleeping 2 ...

为什么launch没有例外?

【问题讨论】:

    标签: exception kotlin kotlin-coroutines


    【解决方案1】:

    TimeoutCancellationException 是CancellationException 的子类。 在 launched 的 Coroutine 中抛出的 CancellationExceptions 不会传播到任何异常处理程序,不会传播到 CoroutineExceptionHandler,也不会传播到线程的未捕获异常处理程序(在您的第一个示例中调用了最后一个异常处理程序)。

    这是您的第二个示例的修改版本,其中 CancellationException 被包装在一个普通的 RuntimeException 中(不是 CancellationException)。您将再次看到堆栈跟踪日志:

    import kotlinx.coroutines.*
    
    fun main(args: Array<String>) {
        runBlocking {
            launch {
                try {
                    withTimeout(1300L) {
                        repeat(1000) { i ->
                            println("I'm sleeping $i ...")
                            delay(500L)
                        }
                    }
                } catch (t: CancellationException) { 
                    throw RuntimeException(t)
                }
            }
        }
    }
    

    launch 和 runBlocking 工作方式不同的主要原因是 runBlocking 它应该返回值,但是因为作用域被取消,没有什么可以返回并且它抛出取消异常,对于启动它只是取消协程

    在这里您可以找到更多关于协程和异常的信息: https://link.medium.com/HEhVwUxOkY

    【讨论】:

      【解决方案2】:

      Cancellation is tightly bound with exceptions. Coroutines internally use CancellationException for cancellation, these exceptions are ignored by all handlers, so they should be used only as the source of additional debug information, which can be obtained by catch block.

      launch builder 忽略 TimeoutCancellationException

      The TimeoutCancellationException that is thrown by withTimeout is a subclass of CancellationException. We have not seen its stack trace printed on the console before. That is because inside a cancelled coroutine CancellationException is considered to be a normal reason for coroutine completion. However, in this example we have used withTimeout right inside the main function.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-13
        • 1970-01-01
        • 1970-01-01
        • 2021-11-13
        • 2019-10-17
        • 1970-01-01
        • 2018-05-26
        • 1970-01-01
        相关资源
        最近更新 更多