【问题标题】:CoroutineScope cannot be reused after an exception thrown抛出异常后无法重用 CoroutineScope
【发布时间】:2020-01-31 01:48:27
【问题描述】:

我有一个实现 CoroutineScope 的类,它有一个函数run,它有一个参数供我测试是否要抛出异常。 在示例中,我发现第二个run 调用中的launch 内的代码块实际上并未执行。这是预期的行为吗?我花了一些时间才发现原始代码中的问题,因为在我编写示例代码进行测试之前,日志没有说明任何内容。如果这是有意的,解决问题的最佳做法是什么?我想要实现的是重用run函数,并且能够在该函数内部捕获异常。

package coroutine.exceptions

import kotlinx.coroutines.*

fun log(msg: String) = println("$msg (${Thread.currentThread().name})")
val exceptionHandler = CoroutineExceptionHandler { _, e ->
    log(e.localizedMessage)
}

fun main() = runBlocking {

    val test1 = TestReuseCoroutineAfterException("test1")
    test1.run(true)
    delay(2000)
    test1.run(false)
    delay(2000)

    log("finished")
}


class TestReuseCoroutineAfterException(private val testName: String) :
    CoroutineScope by CoroutineScope(Dispatchers.Default) {

    fun run(throwException: Boolean) {
        log("$testName: call - started")
        launch(exceptionHandler) {
            if (throwException)
                throw Exception("$testName: call - throw exception")
            else
                log("$testName: call - done")
        }
        log("$testName: call - ended")
    }

}

输出:

test1: call - started (main)
test1: call - ended (main)
test1: call - throw exception (DefaultDispatcher-worker-1)
test1: call - started (main)
test1: call - ended (main)
finished (main)

Process finished with exit code 0

【问题讨论】:

    标签: kotlin kotlin-coroutines


    【解决方案1】:

    当您像这样创建CoroutineScope 时:

    CoroutineScope(Dispatchers.Default)
    

    它使用Job() 作为它的Job,如果在子协程中抛出异常,Job() 会取消作用域。如果您不想在孩子失败时取消整个范围,请使用SupervisorJob

    CoroutineScope(Dispatchers.Default + SupervisorJob())
    

    在此更改后,您的代码将打印:

    test1: call - started (main)
    test1: call - ended (main)
    test1: call - throw exception (DefaultDispatcher-worker-1)
    test1: call - started (main)
    test1: call - ended (main)
    test1: call - done (DefaultDispatcher-worker-2)
    finished (main)
    

    【讨论】:

      猜你喜欢
      • 2021-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      • 2019-08-30
      • 1970-01-01
      • 2013-05-24
      • 2018-01-01
      相关资源
      最近更新 更多