首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CoroutineScope取消

CoroutineScope取消
EN

Stack Overflow用户
提问于 2020-12-10 17:44:44
回答 2查看 1.6K关注 0票数 2

我完全理解suspendCoroutine和suspendCancellableCoroutine在我的示例中是如何工作的。但是我想知道为什么println(“我完成了”)(视图块中的第13秒行)在调用viewScope.cancel()之后执行。我可以在这一行之前用isActive标志修复它,但是我不想检查每一行。我在那里错过了什么。我怎样才能取消范围呢?谢谢

代码语言:javascript
复制
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 :)")
}
EN

回答 2

Stack Overflow用户

发布于 2020-12-10 18:47:44

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

coroutine代码的取消需要操作

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

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

票数 5
EN

Stack Overflow用户

发布于 2021-07-08 17:08:10

协同取消是合作的

您应该在println("I finished")之前检查coroutine是否仍然处于活动状态,如果您希望如果coroutine被取消,则不执行该语句,如下所示:

代码语言:javascript
复制
if (isActive)
    println("I finished")

为什么会这样呢?

Coroutines不需要被分派到另一个线程上。因此,虽然线程提供了中止的方法,这是在运行时(例如JVM或ART)在系统级或用户级实现的,但是没有线程支持的协同任务无论如何也不能被取消,因为唯一可以做的事情是抛出异常,但这会中止整个当前执行上下文(即线程),而其他coroutines可能正在运行。

其他答案提到了繁重的计算,但这显然是错误的。不管你在做什么,计算量是否很大--协同任务不能强制取消;它们的取消只是一个被取消的请求,由coroutine机构使用CoroutineScope property isActive来处理取消请求,该属性isActive获得一个布尔值,指示是否继续执行coroutine的工作,如果是true;或者取消,如果是false的话。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65239627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档