gpt4 book ai didi

android - 协程中的 Job.Cancel 与 Scope.Cancel 有什么区别?

转载 作者:行者123 更新时间:2023-12-05 03:17:33 31 4
gpt4 key购买 nike

我一直在探索协程,我很惊讶地发现在 Job 上调用的 cancel 实际上并没有取消作业,而 cancel 在 scope 上调用会立即取消从 scope 启动的协程。谁能解释一下?

作业取消示例。

/**
* This never stops
*/
@Test
fun coroutineTest7() = runBlocking {
val job = launch(Dispatchers.IO) {
var count = 0
while(true){
if(isActive){
println("Hello ${count++}")
}
else {
println("Job Cancelled but this will still get printed")
}
Thread.sleep(500)
}
}
Thread.sleep(6000)
job.cancel()
Unit
}

范围取消示例

/**
* This gets cancelled after six seconds
*/
@Test
fun coroutineTest5() = runBlocking {
val newScope = CoroutineScope(Dispatchers.IO)
newScope.launch(Dispatchers.IO) {
var count = 0
while(true){
Thread.sleep(500)
println("Hello ${count++}")
}
}
Thread.sleep(6000)
newScope.cancel()
Unit
}

最佳答案

在您的第一个代码块中,您的作业不配合取消。它有一个死循环,没有调用任何配合取消的suspend函数,所以没有办法退出循环,也没有办法取消Job。由于 runBlocking 只要其子协程在运行,它就会一直运行,因此它会永远等待作业完成。

在你的第二个代码块中,你的 Job 仍然不配合取消,但由于它是在不同的 CoroutineScope 而不是 runBlocking 的范围内启动的,runBlocking 不会'等待作业完成。因此,尽管您的 Job 一直在运行,runBlocking 将在 newScope.cancel() 调用后立即返回,从而使您的应用进程得以退出并缩短行为不当的协程。我怀疑如果您在此单元测试套件中有其他长时间运行的测试,您可能会在其他测试期间继续看到该作业日志记录,直到进程退出。

可以修改第二个测试在runBlocking之后继续等待,看Job是否还在后台继续运行:

@Test
fun coroutineTest5() {
runBlocking {
val newScope = CoroutineScope(Dispatchers.IO)
newScope.launch(Dispatchers.IO) {
var count = 0
while(true){
Thread.sleep(500)
println("Hello ${count++}")
}
}
Thread.sleep(6000)
newScope.cancel()
println("Cancelled scope")
Thread.sleep(2000)
}
println("Run blocking returned")
Thread.sleep(2000)
println("Returning from test")
}

关于android - 协程中的 Job.Cancel 与 Scope.Cancel 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74111598/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com