Search code examples
androidkotlinasynchronousscopekotlin-coroutines

coroutineScope doesnt wait for child coroutines?


i try to learn coroutines in Kotlin and now i have a problem with some code i played with in the Kotlin Playground.

I have two suspend-functions. One with a delay of 3seconds. I will call both functions inside a coroutinescope. If i call getWeatherReport() in the main, i expect that it prints both messages nearly at the same time, because its said, that coroutinescopes waits for all its child-coroutines to be done with computation, and then returns. But why does here 30 Degrees get printed immediately after 100 ms?

From the official doc: "This function returns as soon as the given block and all its children coroutines are completed." What exactly does it mean the function returns?

suspend fun getWeatherReport() = coroutineScope {


launch { getTemperature() }
launch { getWind() }

}


suspend fun getTemperature(){
delay(100)
println("30 Degrees")
}

suspend fun getWind(){
delay(3000)
println("Wind by North")
}

This is how i call in main:

fun main(args: Array<String>) {
runBlocking {

   getWeatherReport()
   }
 }

Solution

  • Let's explain coroutineScope with simpler (or I'd say more appropriate) case.

    suspend fun getText() = coroutineScope {
        delay(1000)
        println("Block done")
        "Hello world"
    }
    
    suspend fun getTextWithChild() = coroutineScope {
        launch {
            delay(3000)
            println("Child done")
        }
        delay(1000)
        println("Block done")
        "Hello world"
    }
    
    suspend fun main(args: Array<String>) {
       println(getText())
       println(getTextWithChild())
    }
    
    

    Both getText functions execute their main block and we get "Block Done" printed after a second. At this point they have their return value of "Hello World" ready.

    Now we can notice the difference in behavior that "This function returns as soon as the given block and all its children coroutines are completed".

    In first case it's straightforward - since there are no children it returns immediately and main can print "Hello world".

    In second case - despite finishing the block coroutineScope is not done yet. It still has an active child job that was launched within it - only after additional 2000 ms pass we see "Child done" printed which means it's finished and the scope can return. Finally we see "Hello world" printed from main.