关闭后忽略协程通道的报价
Ignoring offers to coroutine channels after closing
是否有一种好方法可以让频道在关闭后忽略优惠而不抛出异常?
目前,似乎只有 try catch 可以工作,因为 isClosedForSend
不是原子的。
或者,如果我根本不关闭频道会有问题吗?
对于我的特定用例,我使用通道作为 Android 实时数据的替代方案(因为除了从任何线程发送值和从主线程监听之外,我不需要任何好处)。在那种情况下,我可以通过只在我想要时发送值的生产者收听频道,而忽略所有其他输入。
理想情况下,我有一个解决方案,其中 ReceiveChannel
仍然可以完成收听,但 SendChannel
在提供新值时永远不会崩溃。
频道抛出此异常 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)
}
}
您会注意到,由于通道关闭,生产者将开始打印 "It's fine",但消费者仍将能够读取前 5 个值。
关于你的第二个问题:视情况而定。
通道没有这么大的开销,挂起的协程也没有。但是泄漏就是泄漏,你知道的。
我最终将 an issue 发布到存储库,解决方案是使用 BroadcastChannel
。您可以通过 openSubscription
创建一个新的 ReceiveChannel
,关闭它不会关闭 SendChannel
。
这更准确地反映了 RxJava 的 PublishSubject
是否有一种好方法可以让频道在关闭后忽略优惠而不抛出异常?
目前,似乎只有 try catch 可以工作,因为 isClosedForSend
不是原子的。
或者,如果我根本不关闭频道会有问题吗? 对于我的特定用例,我使用通道作为 Android 实时数据的替代方案(因为除了从任何线程发送值和从主线程监听之外,我不需要任何好处)。在那种情况下,我可以通过只在我想要时发送值的生产者收听频道,而忽略所有其他输入。
理想情况下,我有一个解决方案,其中 ReceiveChannel
仍然可以完成收听,但 SendChannel
在提供新值时永远不会崩溃。
频道抛出此异常 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)
}
}
您会注意到,由于通道关闭,生产者将开始打印 "It's fine",但消费者仍将能够读取前 5 个值。
关于你的第二个问题:视情况而定。
通道没有这么大的开销,挂起的协程也没有。但是泄漏就是泄漏,你知道的。
我最终将 an issue 发布到存储库,解决方案是使用 BroadcastChannel
。您可以通过 openSubscription
创建一个新的 ReceiveChannel
,关闭它不会关闭 SendChannel
。
这更准确地反映了 RxJava 的 PublishSubject