Paulius Ruminas
02/25/2019, 6:37 AMrunBlocking {
val producer = async {
produce {
send(1)
send(2)
send(3)
}
}
launch {
producer.await().consumeEach { println(it) }
}
}
gildor
02/25/2019, 6:40 AMasync
never returns, just suspend untill all child coroutines are finished (which doesn’t happen in your case).
Actual problem that you never call consumeEach
, because await()
never returnPaulius Ruminas
02/25/2019, 6:43 AMgildor
02/25/2019, 6:43 AMproduce
without relation to async
using GlobalScope. but it’s not a recommended way to work with scopes, this is why I’m asking about your use casePaulius Ruminas
02/25/2019, 6:54 AMclass A {
suspend fun startGeneratingData() = coroutineScope {
produce {
send(1)
send(2)
send(3)
}
}
}
class B {
suspend fun startGeneratingData() = coroutineScope {
produce {
send(1)
send(2)
send(3)
}
}
}
enum class GeneratorType {
A, B
}
class C(
private val a: A,
private val b: B,
override val coroutineContext: CoroutineContext
): CoroutineScope {
private val actions = Channel<Action>()
private sealed class Action {
data class Start(val type: GeneratorType): Action()
object Stop: Action()
}
init {
launch {
val job = coroutineContext + Job()
actions.consumeEach { action ->
when (action) {
is Action.Start -> launch(job) {
when (action.type) {
GeneratorType.A -> a.startGeneratingData()
GeneratorType.B -> b.startGeneratingData()
}
}
Action.Stop -> job.cancelChildren()
}
}
}
}
suspend fun start(type: GeneratorType) {
actions.send(Action.Start(type))
}
suspend fun stop(type: GeneratorType) {
actions.send(Action.Stop)
}
}
fun main() = runBlocking {
val c = C(A(), B(), Dispatchers.Unconfined)
c.start(GeneratorType.A)
}
gildor
02/25/2019, 6:55 AMsuspend fun startGeneratingData() = coroutineScope {
produce {
send(1)
send(2)
send(3)
}
}
coroutineScope
which never return if there are any child coroutine in progress, pass CoroutineScope instance to this function or make startGeneratingData()
extension of coroutine scopePaulius Ruminas
02/25/2019, 6:57 AMgildor
02/25/2019, 6:58 AMAction.Stop -> job.cancelChildren()
as I understand you can replace it with cancel() on this channelPaulius Ruminas
02/25/2019, 7:10 AMvar activeProducer: ReceiveChannel<Int>?
Is there any side effects of doing it with a job instead of a mutable variable?gildor
02/25/2019, 7:14 AMPaulius Ruminas
02/25/2019, 8:05 AMcoroutineScope
? It's a noun so from the name i would think that it is factory method to create a coroutine scope not to launch multiple coroutines with the same job. launch
is a verb so one assumes that it will run computations but with coroutineScope
i do not think it is that obvious.gildor
02/25/2019, 8:08 AMi would think that it is factory method to create a coroutine scopeYes, and it creates coroutine scope
Paulius Ruminas
02/25/2019, 8:11 AMgildor
02/25/2019, 8:13 AM