在某些情况下,我想异步地使用ReceiveChannel
来构建produce
,但是它挂了。这是一个简化的示例:
runBlocking {
val deferredChannel = async {
produce<String> { send("foo") }
}
val channel = deferredChannel.await()
println("Got channel")
val value = channel.receive()
println("Got value $value")
}
都没有 println
被点击。可能存在某种协程死锁,但我不清楚在何处/如何进行。
如何异步生成ReceiveChannel
?
编辑:如果我将produce
更改为produce(capacity = 1)
,则可以使用,但是为什么呢?至少与生产者的能力无关,await()
是否应该成功?如果我想保持容量= 0,又该怎么办?
答案 0 :(得分:1)
如果我将生产方式更改为生产方式(产能= 1),这是可行的,但是为什么呢?不管生产者的能力如何,至少await()是否应该成功?
检查您调用的produce()
方法上的docs,特别是容量参数上的docs和我们拥有的Channel
(重点是我):
当容量为0 时-创建RendezvousChannel。 该频道根本没有任何缓冲区。仅当发送和接收调用在时间上相遇时,元素才从发送方转移到接收方(集合点),因此发送将挂起,直到另一个协程调用receive ,并且接收挂起,直到另一个协程调用发送。
这可能是它挂起的原因。您正在send
线程上调用async
,然后在await
上调用它……但是,正如文档所说,还没有其他例程调用receive
。 。,因此它将挂起,直到发生这种情况,然后挂起。
检查Channel上的同一链接,我们还看到为什么给它一个大于0的数字可以解决此问题(强调我的问题):
容量为正值,但小于UNLIMITED时,它将创建具有给定容量的基于阵列的通道。该通道具有固定容量的阵列缓冲区。 发件人仅在缓冲区已满时挂起,接收方仅在缓冲区为空时挂起。