有没有一种好方法让渠道在关闭后忽略商品而不会引发异常?
当前,似乎只有try catch才有效,因为isClosedForSend
不是原子的。
或者,如果我根本不关闭通道,是否有问题? 对于我的特定用例,我使用通道替代Android livedata(因为除了从任何线程发送值和从主线程侦听之外,我不需要任何其他好处)。在那种情况下,我可以通过仅在需要时发送值的生产者来监听通道,而忽略所有其他输入。
理想情况下,我将有一个解决方案,其中ReceiveChannel
仍可以完成监听,但是在SendChannel
提供新值时永远不会崩溃。
答案 0 :(得分:0)
渠道会抛出此异常by design,以作为正确沟通的手段。
如果绝对必须具有这样的内容,则可以使用这种扩展功能:
private suspend fun <E> Channel<E>.sendOrNothing(e: E) {
try {
this.send(e)
}
catch (closedException: ClosedSendChannelException) {
println("It's fine")
}
}
您可以使用以下代码对其进行测试:
val channel = Channel<Int>(capacity = 3)
launch {
try {
for (i in 1..10) {
channel.sendOrNothing(i)
delay(50)
if (i == 5) {
channel.close()
}
}
println("Done")
}
catch (e: Exception) {
e.printStackTrace()
}
finally {
println("Finally")
}
}
launch {
for (c in channel) {
println(c)
delay(300)
}
}
您会注意到,由于关闭了通道,生产者将开始打印“很好”,但是消费者仍然可以读取前5个值。
关于第二个问题:这取决于。
通道没有这么大的开销,挂起的协程也没有。但是,泄漏就是泄漏。
答案 1 :(得分:0)
我最终将an issue发布到仓库中,解决方案是使用BroadcastChannel
。您可以通过ReceiveChannel
创建一个新的openSubscription
,如果将其关闭将不会关闭SendChannel
。
这更准确地反映了RxJava的PublishSubject