Reputation: 4152
Kotlin says
fun main() = runBlocking { // this: CoroutineScope
launch {
delay(200L)
println("Task from runBlocking")
}
coroutineScope { // Creates a coroutine scope
launch {
delay(500L)
println("Task from nested launch")
}
delay(100L)
println("Task from coroutine scope") // This line will be printed before the nested launch
}
println("Coroutine scope is over") // This line is not printed until the nested launch completes
}
in above example what i expect is :-
launch
will executed and it comes to delay(200L)
coroutineScope
and comes to delay(500L)
& delay(100L)
println("Coroutine scope is over")
.This is what my understanding on runBlocking
and coroutineScope
. Which is not working as expected.
the Output is
Task from coroutine scope
Task from runBlocking
Task from nested launch
Coroutine scope is over
Can anyone kindly explain in a easy way to understand this.
Upvotes: 4
Views: 2085
Reputation: 4152
I modified the code a little
fun main() = runBlocking(Dispatchers.Default) {
var i = 1
launch {
println("Task from runBlocking")
while (i < 10) {
delay(30L)
println(i++)
}
}
coroutineScope { // Creates a coroutine scope
launch {
delay(200L)
println("Task from nested launch")
}
delay(100L)
println("Task from coroutine scope") // This line will be printed before the nested launch
}
println("Coroutine scope is over")
}
Output
Task from runBlocking
1
2
3
Task from coroutine scope
4
5
6
Task from nested launch
Coroutine scope is over
7
8
9
the observation i made is,
delay(100L) is equal to approximate 3 times delay(30L)
delay(200L) is equal to approximate 6 times delay(30L)
So, after 3 Task from coroutine scope
and after 6 Task from nested launch
is printed.
then exactly after this Coroutine scope is over
but you can still see the loop printed 7,8,9
.
This is because like runBlocking
coroutineScope
waits for all its members to execute by suspending underlying threads. But understand, those threads first work on members of coroutineScope
not on runBlocking
.
Hence, it is printing Task from coroutine scope
and Task from nested launch
before Coroutine scope is over
Upvotes: 2
Reputation: 560
launch
causes the block to be executed asynchronously, so the call to launch
returns immediately, and the coroutine continues its running and doesn't wait for the execution of the launched block.
Therefore, immediately after runBlocking
is called, the first and the second launch
are called one after another, and immediately after that the coroutine is suspended on delay(100L)
.
After 100ms the coroutine is resumed and prints "Task from coroutine scope", and then the execution of the nested coroutine-scope's block ends. A coroutine-scope always waits for the end of execution of all the jobs it has launched, so it waits here for 500ms.
Meanwhile, the two launched blocks are executed, so "Task from runBlocking" is printed first (after 200ms from the start), and then "Task from nested launch" is printed (after 500ms from the start).
Eventually, after the internal launched job has been completed, the internal coroutine-scope finishes waiting, and the external coroutine continues and prints "Coroutine scope is over".
This is the story. I hope it helps a little to understand how the code is executed and why the order of printing is like that.
Upvotes: 6