首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Kotlin产出函数在取消协同例程时不协同

Kotlin产出函数在取消协同例程时不协同
EN

Stack Overflow用户
提问于 2021-06-10 15:20:07
回答 2查看 62关注 0票数 0

与FlowCollector中的emit()函数不同,yield函数在取消协同例程时不协同工作。以下是示例程序:

代码语言:javascript
运行
复制
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeoutOrNull

fun main(): Unit = runBlocking {
    withTimeoutOrNull(5000) {
        getFlow().collect { println("printing flow iteration $it on ${Thread.currentThread().name}") }
    }

    withTimeoutOrNull(5000) {
        getSequence().forEach { println("printing sequence iteration $it on ${Thread.currentThread().name}") }
    }
}

fun getSequence() = sequence<Int> {
    for (i in 1..10) {
        wasteCpuCycles(1000)
        yield(i)
    }
}

fun getFlow() = flow<Int> {
    for (i in 1..10) {
        wasteCpuCycles(1000)
        emit(i)
    }
}

fun wasteCpuCycles(durationInMillis: Int) {
    val endTime = System.currentTimeMillis() + durationInMillis
    while (endTime >= System.currentTimeMillis()) {
    }
}

以下是执行的输出:

在main上打印流程迭代1

在main上打印流程迭代2

在main上打印流程迭代3

在main上打印流程迭代4

在main上打印序列迭代1

在main上打印序列迭代2

在main上打印序列迭代3

在main上打印序列迭代4

在main上打印序列迭代5

在main上打印序列迭代6

在main上打印序列迭代7

在main上打印序列迭代8

在main上打印序列迭代9

在main上打印序列迭代10

根据that和emit函数的签名,我希望这两个函数都参与协作例程的协作取消。但是通过查看输出可以发现,即使协同例程从超时中取消,产量也不会停止。由于两者都挂起了功能,这种行为背后的原因可能是什么?

EN

回答 2

Stack Overflow用户

发布于 2021-06-10 15:45:58

与flow不同,序列不是异步的。因此,SequenceScope内部的收益函数是不可取消的,并且对协同例程的运行状态没有影响。

票数 0
EN

Stack Overflow用户

发布于 2021-06-10 16:53:15

请注意,sequence { }函数和next()都是不可挂起的,它们也不会接收协程上下文/作用域。我猜这意味着在序列中运行的协程没有附加到调用者的协程上下文中,它不参与其结构化并发。因此,即使withTimeoutOrNull()取消了在其中运行的协程,sequence { }内部的协程也会从上面分离出来,并且不会被通知取消。

至少这是我的理解,我可能会错过一些东西。

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

https://stackoverflow.com/questions/67916479

复制
相关文章

相似问题

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