将频道桥接到序列

时间:2017-07-28 08:18:41

标签: multithreading kotlin coroutine

此代码基于Coroutines guide example: Fan-out

val inputProducer = produce<String>(CommonPool) {
    (0..inputArray.size).forEach {
        send(inputArray[it])
    }
}

val resultChannel = Channel<Result>(10)

repeat(threadCount) {
    launch(CommonPool) {
        inputProducer.consumeEach {
            resultChannel.send(getResultFromData(it))
        }
    }
}

创建可提供结果的Sequence<Result>的正确方法是什么?

2 个答案:

答案 0 :(得分:3)

您可以从.iterator()获取通道ReceiveChannel,然后将该通道迭代器包装到Sequence<T>中,实现其正常Iterator<T>阻止等待每个结果请求:

fun <T> ReceiveChannel<T>.asSequence(context: CoroutineContext) =
    Sequence {
        val iterator = iterator()
        object : AbstractIterator<T>() {
            override fun computeNext() = runBlocking(context) {
                if (!iterator.hasNext())
                    done() else
                    setNext(iterator.next())
            }
        }
    }

val resultSequence = resultChannel.asSequence(CommonPool)

答案 1 :(得分:0)

我遇到了同样的问题,最后我想出了一个非常不寻常/复杂的解决方案:

fun Channel<T>.asSequence() : Sequence<T> {
    val itr = this.iterator()
    return sequence<Int> {
      while ( runBlocking {itr.hasNext()} ) yield( runBlocking<T> { itr.next() } )
    }
}

我认为这不是特别有效(与@hotkey提供的功能一起使用),但至少对我有一定吸引力。