在不使用显式 Job() 对象的情况下取消父作业
Posted
技术标签:
【中文标题】在不使用显式 Job() 对象的情况下取消父作业【英文标题】:Cancelling parent job without using explicit Job() object 【发布时间】:2020-10-02 05:33:54 【问题描述】:在下面的代码中,我创建了两个作业,然后我取消了父作业。我希望子作业会被取消,但是,子作业不会被取消,它们仍然处于活动状态。为什么?
注意:我知道这个问题很容易解决,方法是创建一个 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
【问题讨论】:
【参考方案1】:child1
和 child2
作业不是 currentJob
的子级。他们是coroutineScope
Job 的孩子。我们可以说currentJob
、child1
和child2
是“兄弟姐妹”。如果您想全部取消它们,请取消 coroutineScope
而不是:coroutineScope.cancel()
。或者让他们成为currentJob
的孩子并取消currentJob
:
val currentJob = coroutineScope.launch
child1 = launch
delay(500)
child2 = launch
delay(500)
Thread.sleep(300L)
currentJob.cancel()
【讨论】:
@oiyio 在内部传递的 CoroutineScope 对象上调用启动,该对象将这些任务作为子项注册到其作业中。 天哪。我现在意识到了...好吧,您建议的代码会按我的预期打印孩子。但是 coroutineScope.isActive 返回仍然是 true。为什么? @oiyio 因为您只取消了currentJob
,这将取消child1
和child2
。试试这个coroutineScope.cancel()
取消整个范围。以上是关于在不使用显式 Job() 对象的情况下取消父作业的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有显式比较对象的情况下从 Container 对象构造 std::priority_queue 的实例?