StragaSevera
01/31/2021, 1:42 PMstart() method, but does not happen if I remove the class and copy contents of the start() method to the main() function. It seems like there is some caching issue...Ian Lake
01/31/2021, 4:09 PMZach Klippenstein (he/him) [MOD]
01/31/2021, 4:33 PMcountTo coroutines are running as children of your scope property, not as children of the coroutine running calculate. So when you cancel the coroutine that the calculate function is running in, it doesn’t do anything. To fix this, and in general, whenever you have a suspend function, any coroutines you launch should usually be children of the current scope, not of an external one. You can get the current scope in a suspend function using the coroutineScope function. Your calculate function should look like this:
private suspend fun calculate(): Int {
// Wrap with coroutineScope.
return coroutineScope {
// Now, inside this lambda, this is the CoroutineScope of the current
// coroutine, so you can call async without an explicit receiver and it
// will launch a child of the current scope.
val a = async { countTo(10) }
val b = async { countTo(20) }
// Need a qualified return now since this is in a lambda, but
// you could also just omit the return keyword entirely.
return@coroutineScope a.await() + b.await()
}
}
This also takes advantage of one of the other features of structured concurrency – the coroutineScope function won’t return until all the coroutines launched inside it have completed, which means it’s much harder to accidentally forget to join a coroutine and leak it.Zach Klippenstein (he/him) [MOD]
01/31/2021, 4:34 PMsuspend fun calculate(): Int = coroutineScope {
val a = async { countTo(10) }
val b = async { countTo(20) }
a.await() + b.await()
}StragaSevera
01/31/2021, 5:32 PMasync should be wrapped in coroutineScope?Youssef Shoaib [MOD]
01/31/2021, 5:40 PMso any call of a suspend function starts a new coroutineNo, it's specifically that any call that starts a coroutine (i.e. any call that's defined as an extension on coroutineScope) should be wrapped in a coroutineScope block if inside a normal suspend function. If you call any other suspend function then you don't need that coroutineScope block, it's only needed here because
async is a call that starts a coroutineStragaSevera
01/31/2021, 5:42 PMZach Klippenstein (he/him) [MOD]
01/31/2021, 6:42 PMCoroutineScope – not both.StragaSevera
01/31/2021, 6:42 PMZach Klippenstein (he/him) [MOD]
01/31/2021, 6:48 PMStragaSevera
01/31/2021, 6:49 PM