简体   繁体   English

Coroutine与SupervisorJob - 取消行为

[英]Coroutine with a SupervisorJob - cancellation behaviour

I need to implement some exception handling in my code so I've the following coroutine test code which launched from a fragment; 我需要在我的代码中实现一些异常处理,所以我有以下从一个片段启动的协程测试代码;

private val scoped = CoroutineScope(Dispatchers.Default + SupervisorJob())

...

val handler = CoroutineExceptionHandler { _, exception ->
        println("TAG-Caught $exception")
    }

scope.launch(handler) {

        val job1 = launch {
            println("TAG-first job is running")
            delay(200)
        }

        testParentChildWithExceptionWithSupervision()

        launch {
            println("TAG-third job is running")
        }
    }

where the method testParentChildWithExceptionWithSupervision looks like; testParentChildWithExceptionWithSupervision方法的样子;

suspend fun testParentChildWithExceptionWithSupervision() {

    supervisorScope {

        val job1 = launch {
            println("TAG-running first (inner) child")
            delay(200)
            throw ArithmeticException()
        }

        val job2 = launch {
            job1.join()
            println("TAG-First child is cancelled: ${job1.isCancelled}, but second one is still active")
            delay(200)
        }

        job1.join()
        println("TAG-second child is cancelled: ${job2.isCancelled}")

        println("TAG-ENDING")
    }
}

The output is as I expected; 输出是我预期的;

在此输入图像描述

The thing is as soon as I change supervisorScope to coroutineScope in the suspending function, I see that root scope (with the SpervisorJob) do not carry on with her childs; 事情是,当我在暂停功能中将supervisorScope更改为coroutineScope时,我看到根范围(使用SpervisorJob)不会继续她的孩子;

suspend fun testParentChildWithExceptionWithoutSupervision() {

        coroutineScope {

            val job1 = launch {
                println("HH-doing first child")
                delay(200)
                throw ArithmeticException()
            }

            val job2 = launch {
                job1.join()
                println("HH-First child is cancelled: ${job1.isCancelled}, but second one is still active")
                delay(200)
            }

and I get this output instead; 而我得到了这个输出;

在此输入图像描述

So nothing seems to be carried on in the root scope after having an exception even the scope has a supervisor job. 因此,即使范围具有主管作业,在具有异常之后似乎也没有在根范围中进行任何操作。 I bet I miss sth but not able to see it. 我打赌我想念......但却无法看到它。 Can someone please explain the reason behind it? 有人可以解释背后的原因吗?

If you check out the documentation on suspend fun coroutineScope , you'll find this: 如果你查看suspend fun coroutineScope文档 ,你会发现:

The method may throw a [...] corresponding unhandled Throwable if there is any unhandled exception in this scope (for example, from a crashed coroutine that was started with launch in this scope). 该方法可以抛出一个[...]与未处理Throwable如果在此范围内的任何未处理的异常(例如,从已开始崩溃的协同程序launch在此范围内)。

This is the case that happens in your code: the "first (inner) child" crashes with an unhandled ArithmeticException . 这是在您的代码中发生的情况:“第一个(内部)子”与未处理的ArithmeticException崩溃。 This becomes the result of testParentChildWithExceptionWithSupervision and at the call site, nothing handles it. 这成为testParentChildWithExceptionWithSupervision的结果,在调用站点,没有任何处理它。 Therefore it proceeds to crash the parent as well — not through the mechanism of propagating coroutine cancellation, but through the basic exception mechanism. 因此它也会使父进程崩溃 - 不是通过传播协程取消的机制,而是通过基本的异常机制。 SupervisorJob makes no difference here, the main block of code completes abruptly with that exception unhandled, which is why you see it printed by the unhandled exception handler. SupervisorJob在这里没有任何区别,主要的代码块突然完成,未处理的异常,这就是为什么你看到它由未处理的异常处理程序打印。

If you modify your code to do this: 如果您修改代码来执行此操作:

    try {
        testParentChildWithExceptionWithSupervision()
    } catch (e: ArithmeticException) {
        println("ArithmeticException in main block")
    }

you'll see the main coroutine proceed until the end. 你会看到主协程一直持续到最后。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM