首页 > 解决方案 > CoroutineExceptionHandler “吞下”异常,但不调用 handleException() 函数

问题描述

当我执行这个单元测试时,我在输出中看到异常通知(可能是默认异常处理程序打印它):

@Test
fun uncaughtException() {
    runBlocking {
        val scope = CoroutineScope(Dispatchers.Default)
        val job = scope.launch() {
            delay(100)
            println("inside coroutine")
        }
        scope.launch {
            delay(50)
            throw Exception()
        }
        job.join()
    }
    Thread.sleep(100)
    println("test completed")
}

然后我尝试将我的自定义 CoroutineExceptionHandler 添加到范围的上下文中:

@Test
fun exceptionHandler() {
    runBlocking {
        val exceptionHandler = CoroutineExceptionHandler { _, throwable -> {
            println("Caught exception")
        }}
        val scope = CoroutineScope(Dispatchers.Default + exceptionHandler)
        val job = scope.launch() {
            delay(100)
            println("inside coroutine")
        }
        scope.launch {
            delay(50)
            throw Exception()
        }
        job.join()
    }
    Thread.sleep(100)
    println("test completed")
}

这使得先前关于异常的消息消失(这可能意味着我的自定义处理程序替换了默认处理程序),但handleException()我的自定义处理程序没有被调用,并且我在输出中看不到“捕获异常”(只有“测试完全的”)。

我想这可能与单元测试有关,所以我在 Android 应用程序中尝试了相同的代码。结果是一样的:出现异常时应用程序不会崩溃(这意味着默认处理程序已被替换),但我的自定义处理程序的handleException()函数没有被调用。

这感觉不对。这是预期的行为还是错误?

标签: kotlinkotlin-coroutines

解决方案


废话,由于额外的一对花括号,我刚刚浪费了整整一个小时。

我写了这个:

    val exceptionHandler = CoroutineExceptionHandler { _, throwable -> {
        println("Caught exception")
    }}

但正确的使用方法是:

    val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
        println("Caught exception")
    }

然后它工作。


推荐阅读