Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';建议推迟Kotlin';什么是构建序列?_Kotlin_Kotlinx.coroutines - Fatal编程技术网

什么';建议推迟Kotlin';什么是构建序列?

什么';建议推迟Kotlin';什么是构建序列?,kotlin,kotlinx.coroutines,Kotlin,Kotlinx.coroutines,我正在尝试轮询一个分页的API,并在新项目出现时向用户提供它们 fun connect(): Sequence<T> = buildSequence { while (true) { // result is a List<T> val result = dataSource.getFirstPage() yieldAll(/* the new data in `result` */) // Blo

我正在尝试轮询一个分页的API,并在新项目出现时向用户提供它们

fun connect(): Sequence<T> = buildSequence {
    while (true) {
        // result is a List<T>
        val result = dataSource.getFirstPage()
        yieldAll(/* the new data in `result` */)

        // Block the thread for a little bit
    }
}
我的第一个想法是使用
delay
功能,但我得到了以下信息:

受限制的挂起函数只能在其受限制的协同例程作用域上调用成员或扩展挂起函数

这是
buildSequence
的签名:

public fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit): Sequence<T>
这是可行的,但似乎不是一个好的解决方案。以前有人遇到过这个问题吗

为什么它不起作用?一些研究 当我们查看
buildSequence
时,可以看到它将
builderAction:suspend SequenceBuilder.->单元
作为其参数。作为该方法的客户,您将能够提供一个
suspend
lambda,该lambda具有
SequenceBuilder
作为其接收器(阅读关于lambda with receiver的内容)
SequenceBuilder
本身用
RestrictSuspension
注释:

@RestrictsSuspension
@SinceKotlin("1.1")
public abstract class SequenceBuilder<in T> ...
正如
RestrictSuspension
文档所述,在
buildSequence
的情况下,您可以将带有
SequenceBuilder
的lambda作为其接收器传递,但可能会有restricted的情况,因为您只能调用“此特定接收器上的其他成员或扩展
suspense
函数”. 这意味着,传递给
buildSequence
的块可以调用
SequenceBuilder
上定义的任何方法(如
yield
yieldAll
)。另一方面,由于该块“被限制调用任意暂停函数”,因此使用
delay
不起作用。生成的编译器错误将验证它:

受限制的挂起函数只能在其受限制的协同例程作用域上调用成员或扩展挂起函数

最后,您需要知道,
buildSequence
创建了一个协同路由,它是同步协同路由的一个示例。在您的示例中,序列代码将通过调用
connect()
在使用序列的同一线程中执行

如何延迟序列? 正如我们所了解的,
buildSequence
创建了一个同步序列。在这里可以使用常规线程阻塞:

fun connect(): Sequence<T> = buildSequence {
    while (true) {
        val result = dataSource.getFirstPage()
        yieldAll(result)
        Thread.sleep(1000)
    }
}
fun connect():Sequence=buildSequence{
while(true){
val result=dataSource.getFirstPage()
产量(结果)
线程。睡眠(1000)
}
}

但是,您真的想阻止整个线程吗?或者,您可以实现所述的异步序列。因此,使用
delay
和其他挂起功能将是有效的。

在序列运行时,您当前的hackaround实际使用了100%的整个CPU线程…耶。同时使用计划执行器+并发队列。请注意,
buildSequence
只能同步延迟:因为协同路由由迭代器运行,所以它总是希望具有适当序列元素的暂停将其作为迭代器的下一项返回。这就是它限制扩展的原因。不过,另一个问题是使用活动等待而不是阻塞线程。谢谢,这很有意义。我没有意识到我正在创建一个同步协程,所以看起来你可以试着写:suspend{delay(delay)},它会工作(至少它会编译)@AntonShkurenko它只是创建并丢弃了一个lambda,即no-op
@RestrictsSuspension
@SinceKotlin("1.1")
public abstract class SequenceBuilder<in T> ...
/**
 * Classes and interfaces marked with this annotation are restricted
 * when used as receivers for extension `suspend` functions. 
 * These `suspend` extensions can only invoke other member or extension     
 * `suspend` functions on this particular receiver only 
 * and are restricted from calling arbitrary suspension functions.
 */
@SinceKotlin("1.1") @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.BINARY)
public annotation class RestrictsSuspension
fun connect(): Sequence<T> = buildSequence {
    while (true) {
        val result = dataSource.getFirstPage()
        yieldAll(result)
        Thread.sleep(1000)
    }
}