首页 > 解决方案 > CoroutineScope 取消

问题描述

我完全了解suspendCoroutine 和suspendCancellableCoroutine 在我的示例中是如何工作的。但我想知道为什么在我调用 viewScope.cancel() 之后执行println("I finished") (第 13 行 - viewscope 块中的第二行)。我可以在此行之前使用 isActive 标志修复它,但我不想检查每一行。我在那里想念什么。我如何也可以取消范围?谢谢

import kotlinx.coroutines.*
import java.lang.Exception
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

fun main() {
    val parentJob = Job()
    val viewScope = CoroutineScope(Dispatchers.IO + parentJob)

    viewScope.launch {
        println(tryMe())
        println("I finished")
    }
    Thread.sleep(2000)
    viewScope.cancel()
    Thread.sleep(10000)
}

suspend fun tryMe() = suspendCoroutine<String> {
    println("I started working")
    Thread.sleep(6000)
    println("Im still working :O")
    it.resume("I returned object at the end :)")
}

suspend fun tryMe2() = suspendCancellableCoroutine<String> {
    println("I started working")
    Thread.sleep(6000)
    println("Im still working :O")
    it.resume("I returned object at the end :)")
}

suspend fun tryMe3() = suspendCancellableCoroutine<String> {
    it.invokeOnCancellation { println("I canceled did you heard that ?") }
    println("I started working")
    Thread.sleep(6000)
    if (it.isActive)
        println("Im still working :O")
    it.resume("I returned object at the end :)")
}

标签: androidkotlincoroutine

解决方案


如果我们只是调用cancel,并不意味着协程工作就会停止。如果您正在执行一些相对繁重的计算,例如从多个文件中读取,则没有什么可以自动阻止您的代码运行。一旦job.cancel被调用,我们的协程就会进入 Canceling 状态。

取消协程代码需要协同

您需要确保您正在实施的所有协程工作都与取消合作,因此您需要定期或在开始任何长时间运行的工作之前检查取消。例如,如果您正在从磁盘读取多个文件,则在开始读取每个文件之前,请检查协程是否已取消。像这样,您可以避免在不再需要时进行 CPU 密集型工作。

来自的所有挂起函数kotlinx.coroutines都是可取消的:withContextdelay。因此,如果您使用其中任何一个,则无需检查取消并停止执行或抛出CancellationException. 但是,如果您不使用它们,请通过检查job.isActiveensureActive()


推荐阅读