gpt4 book ai didi

kotlin - 如何在协程的计算代码中正确处理取消?

转载 作者:行者123 更新时间:2023-12-02 13:35:52 26 4
gpt4 key购买 nike

这是我对协程取消的理解:

If a parent coroutine is canceled, the children will stop too. If a child coroutine throws Exception, the sibling and parent coroutine will notice it and stop.

Except for SupervisorJob, it will continue active even though one of the child coroutines is stopped.



因此,我编写了一个代码片段来练习我的理解。

代码段1
fun main() {
val parentScope = CoroutineScope(SupervisorJob())
parentScope.launch {
val childJob = launch {
try {
println("#1")
Thread.sleep(1_000)
println("#2")
} catch (e: Exception) {
println("#3")
}
}
println("#4")
childJob.cancel()
}
Thread.sleep(2_000)
}

这是我的两个期望:

期望1:
#1 is called first because there's no blocking code between child and parent job.
#4 is called because `Thread.sleep` is blocking.
#3 is called because the childJob is cancelled, even though the coroutine is not finished.

期望2:
#4 is called first because the parent coroutine start first.
#1 is called because even though the childJob is cancelled, there's time for #1 to be executed.

但是,代码段1的实际输出为:
#4
#1
#2

我再次阅读 coroutine docs来发现对于计算代码,我们必须使用 yield或检查协程状态( activecanceledisCompleted)。然后,我进行以下调整:

代码段2
fun main() {
val parentScope = CoroutineScope(SupervisorJob())
parentScope.launch {
val childJob = launch {
try {
println("#1")
Thread.sleep(1_000)
if (isActive) {
println("#2")
}
} catch (e: Exception) {
println("#3")
}
}
println("#4")
childJob.cancel()
}
Thread.sleep(2_000)
}

这次的输出是:
#4
#1

这是我的问题:
  • 在代码片段1中,取消childJob后仍如何执行#2?
  • 在代码段1中,为什么即使调用了childJob也从不执行#3?
  • 在代码片段2中,我们是否真的需要在每次执行协程代码时使用yield或检查协程状态?因为我认为该代码将更难阅读。
  • 我的代码段或对协程的理解是否有问题?

  • 注意:
    我不想将 GlobalScope.runBlocking用于代码段,因为在实际项目中,我们无论如何都不会使用 GlobalScope。我想使用父子作用域和某些生命周期来创建一个与实际项目尽可能接近的示例。

    最佳答案

    In code snippet 1, how is #2 still executed after childJob is canceled?



    仅暂停函数 are cancellable。将 Thread.sleep(1_000)替换为暂停的 delay,它将被取消。

    In code snippet 1, why #3 is never executed even though childJob is called?



    这是因为协程未取消。请参阅第一个问题的答案。

    In code snippet 2, do we really need to use yield or checking coroutine state every time we want to execute a coroutine code? Because in my opinion, the code will be harder to read.



    不,你不应该。每个暂停功能都会检查协程的取消。

    Is there something wrong my code snippet or my understanding of coroutine?



    在使用协程时,了解挂起功能至关重要。 Coroutine Basics文档部分对此进行了很好的解释。也许 SO question会很有用。

    关于kotlin - 如何在协程的计算代码中正确处理取消?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57335077/

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