首页 > 解决方案 > 在不使用显式 Job() 对象的情况下取消父作业

问题描述

在下面的代码中,我创建了两个作业,然后我取消了父作业。我希望子作业会被取消,但是,子作业不会被取消,它们仍然处于活动状态。为什么?

注意:我知道这个问题可以通过创建一个 Job() 对象来轻松解决,然后将 Job 对象提供给协程上下文,然后取消 Job() 对象。我的问题是为什么下面的代码不起作用?如果我想取消父作业,我必须使用显式父参数吗?

fun main() {

    // CoroutineScope
    val coroutineScope = CoroutineScope(Dispatchers.IO)

    var child1 : Job? = null
    var child2 : Job? = null

    // Use
    val currentJob = coroutineScope.launch {
        child1 = coroutineScope.launch {
            delay(500)
        }
        child2 = coroutineScope.launch {
            delay(500)
        }
    }

    Thread.sleep(300L)

    currentJob.cancel()

    println("Job 1 state: ${child1?.status()}")
    println("Job 2 state: ${child2?.status()}")
    println("Parent job is active: ${coroutineScope.isActive}")
    println("Parent job is active: ${currentJob.isActive}")


    Thread.sleep(2000L)
}

输出 :

Job 1 state: Active
Job 2 state: Active
Parent job is active: true
Parent job is active: false

标签: androidkotlinkotlin-coroutines

解决方案


child1child2乔布斯不是的currentJob孩子。他们是coroutineScope约伯的孩子。我们可以说currentJobchild1child2是“兄弟姐妹”。如果您想全部取消,请coroutineScope改为取消:coroutineScope.cancel(). 或者让他们成为currentJob孩子并取消currentJob

val currentJob = coroutineScope.launch {
    child1 = launch {
        delay(500)
    }
    child2 = launch {
        delay(500)
    }
}

Thread.sleep(300L)

currentJob.cancel()

推荐阅读