代码之家  ›  专栏  ›  技术社区  ›  Allan W

关闭后忽略对协作频道的提供

  •  1
  • Allan W  · 技术社区  · 5 年前

    有没有一个好方法可以让渠道在关闭后忽略报价而不引发异常?

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

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

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

    2 回复  |  直到 5 年前
        1
  •  0
  •   Alexey Soshin    5 年前

    通道引发此异常 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个值。

    关于第二个问题:视情况而定。

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

        2
  •  0
  •   Allan W    5 年前

    我最后发了邮件 an issue 对于回购,解决方案是 BroadcastChannel . 您可以创建一个新的 ReceiveChannel 通过 openSubscription ,关闭时不会关闭 SendChannel .

    这更准确地反映了RxJava的 PublishSubject