【问题标题】:onReceiveOrClosed: Already resumedonReceiveOrClosed:已经恢复
【发布时间】:2020-01-14 08:01:54
【问题描述】:

采取以下程序:

package example

import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.selects.select

@InternalCoroutinesApi
fun main() {
    runBlocking {
        val chan = Channel<Unit>()
        chan.close()
        select<Unit> {
            println("Register onReceiveOrClosed.")
            chan.onReceiveOrClosed {
                println("Selected value $it.")
            }
        }
        println("Done.")
    }
}

运行它会给出以下输出:

Register onReceiveOrClosed.
Selected value Closed(null).
Selected value Closed(null).
Exception in thread "main" java.lang.IllegalStateException: Already resumed
    at kotlinx.coroutines.selects.SelectBuilderImpl.resumeWith(Select.kt:458)
    at kotlinx.coroutines.selects.SelectBuilderImpl.handleBuilderException(Select.kt:309)
    at example.ExampleKt$main$1.invokeSuspend(example.kt:28)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
    at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:270)
    at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54)
    at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36)
    at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
    at example.ExampleKt.main(example.kt:10)
    at example.ExampleKt.main(example.kt)

我希望只看到一行Selected value Closed(null),并且我希望不会看到任何异常(但当然,鉴于给予onReceiveOrClosed 的块被执行了两次,异常是有意义的)。

我对@9​​87654326@ 的理解不正确还是onReceiveOrClosed 的错误?

我正在使用 Kotlin 1.3.50 和 kotlinx-coroutines-core:1.3.1。完整示例可在此处获得:https://github.com/frececroka/kotlin-select-onreceiveorclosed

【问题讨论】:

  • 我闻起来像个虫子。

标签: select kotlin kotlin-coroutines kotlinx.coroutines.channels


【解决方案1】:

我认为这是因为当您拨打select 时,频道已经关闭。如果您添加一些延迟,它将正常工作:

@InternalCoroutinesApi
fun main() {
    runBlocking {
        val chan = Channel<Unit>()
        launch {
            chan.close()
        }
        select<Unit> {
            println("Register onReceiveOrClosed.")
            chan.onReceiveOrClosed {
                println("Selected value $it.")
            }
        }
        println("Done.")
    }
}

// prints
// Register onReceiveOrClosed.
// Selected value Closed(null).
// Done.

我不确定这是错误还是预期行为

【讨论】:

  • 我不知道。确保通道没有关闭是可行的,但在大多数情况下,你不能保证这一点。如果 onReceiveOrClosed 真的应该以这种方式工作,那么它的用处将非常有限。
  • 这是一个实验性 API,因此它可能包含问题并且可能会被返工
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2014-02-06
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-06
相关资源
最近更新 更多