Robert Menke
08/22/2019, 2:42 PMChannel, launch a coroutine in CoroutineContext A to send some data through the channel, and then launch a coroutine in CoroutineContext B in order to receive that data?
I threw together a basic example and it looks like you must send/receive to/from a channel in the same CoroutineContext. If so, why is this the case?kingsley
08/22/2019, 2:49 PMAm I able toYes
it looks like you must send/receive to/from a channel in the sameNo. It doesn’t have to be the same coroutine context. You can go through the documentation on channels. It shows several examples of this https://kotlinlang.org/docs/reference/coroutines/channels.htmlCoroutineContext
Robert Menke
08/22/2019, 3:16 PMfun main() {
runBlocking {
produce()
consume()
}
}
val channel = Channel<String>()
suspend fun produce() {
coroutineScope {
launch {
println("Producing")
channel.send("Hello world")
println("Done producing")
}
}
}
suspend fun consume() {
coroutineScope {
launch {
println("Consuming")
val value = channel.receive()
println(value)
}
}
}
My understanding is that the coroutineScope builder creates a new scope that inherits the context of its parent, which in this case is blocking.
I don’t understand why channel.send is blocks the thread in this case though. Done producing is never printed.Robert Menke
08/22/2019, 3:17 PMfun main() {
runBlocking {
produce()
consume()
}
}
val channel = Channel<String>()
fun CoroutineScope.produce() {
launch {
println("Producing")
channel.send("Hello world")
println("Done producing")
}
}
fun CoroutineScope.consume() {
launch {
println("Consuming")
val value = channel.receive()
println(value)
}
}streetsofboston
08/22/2019, 3:44 PMcoroutineScope { ... } only resumes/returns after all its child coroutines have finished.
In your example, the courtineScope calls `launch`creating a child-coroutine that never finishes.
It never finishes, because this child-coroutine calls channeld.send on a RENDEZVOUS channel. the send call will never resume/return.streetsofboston
08/22/2019, 3:44 PMchannel.send never resumes because the channel.receive is never called.streetsofboston
08/22/2019, 3:45 PMchannel.receive is never called because the consume function is never called. This is because produce never resumes/returns in your first code-sample.kingsley
08/22/2019, 3:45 PMproduce and consume are 2 suspending methods, and they both follow structured concurrency which is good.
But this means they will execute sequencially. consume will only get called after produce has completed. But this will never happen because produce will get suspended waiting for a consumer that will never come
The second example is indeed the right way to go about this, since each method is executed concurrently, so produce and consume are able to communicate with each other
If you really want 1 to work though, you could set a buffer value for the channel, but that doesn’t really scale if you want implement a proper channel based setupRobert Menke
08/22/2019, 3:47 PMRobert Menke
08/22/2019, 3:48 PMBecausebeing the key reason 👍only resumes/returns after all its child coroutines have finished.coroutineScope { ... }