【问题标题】:Ignoring offers to coroutine channels after closing关闭后忽略协程通道的提议
【发布时间】:2019-01-14 23:00:54
【问题描述】:

有没有一种好方法可以让频道在关闭后忽略优惠而不会引发异常?

目前,似乎只有 try catch 可以工作,因为 isClosedForSend 不是原子的。

或者,如果我根本不关闭频道,会有问题吗? 对于我的特定用例,我使用通道作为 Android livedata 的替代方案(因为除了从任何线程发送值并从主线程侦听之外,我不需要任何好处)。在这种情况下,我可以通过仅在我想发送值时发送值的生产者来收听通道,而忽略所有其他输入。

理想情况下,我有一个解决方案,ReceiveChannel 仍然可以完成收听,但SendChannel 在提供新值时永远不会崩溃。

【问题讨论】:

    标签: kotlin kotlinx.coroutines


    【解决方案1】:

    频道抛出此异常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 个值。

    关于你的第二个问题:这取决于。

    通道没有这么大的开销,挂起的协程也没有。但是泄漏就是泄漏,你知道的。

    【讨论】:

    • 谢谢。我最终被重定向到 github repo 中的an issue,解决方案是使用BroadcastChannel 来模仿PublishSubject 之类的东西。泄漏明智,它只是一个与 ui 无关的布尔值或 int,所以它应该没问题
    【解决方案2】:

    我最终将an issue 发布到了repo,解决方案是使用BroadcastChannel。您可以通过openSubscription 创建一个新的ReceiveChannel,其中关闭它不会关闭SendChannel

    这更准确地反映了 RxJava 的PublishSubject

    【讨论】:

      猜你喜欢
      • 2022-01-28
      • 2016-09-11
      • 1970-01-01
      • 2013-07-05
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多