I'm launching a coroutine and I want it to finish before I resume execution of main thread.
My code simplified looks like this:
fun hello() {
for (i in 0..100) {
println("hello")
}
}
fun main(args: Array<String>) {
val job = GlobalScope.launch { hello() } //launch parallel
GlobalScope.launch { job.join() } //try to wait for job to finish
print("done")
}
The problem is, because job.join()
needs to be within a coroutine, the main line of execution is deferred to "done", so the output looks like this:
donehello
hello
hello
hello
I want to wait for the job to complete, like using sync.WaitGroup
in Go. So my output would deterministically look like this:
hello
hello
hello
hello
...
done
How do I accomplish this?
So this is the object of deferred then we do whatever processing we need in that program. Then we actually need the value we have to await() function. So this will pause the execution until the value is available for our main program. So we are simply waiting for a value to be available.
A thread can only execute one coroutine at a time, so the framework is in charge of moving coroutines between threads as necessary.
Which coroutine gets suspended? The outer async starts a coroutine. When it calls computation() , the inner async starts a second coroutine. Then, the call to await() suspends the execution of the outer async coroutine, until the execution of the inner async 's coroutine is over.
The async/await pattern is built on two functions: async() to wrap the function call and the resulting value in a coroutine, and await() , which suspends code until the value is ready to be served.
Actually for your sample the job.join()
is the way to ensure that at this point it waits until the given job is finished. Unfortunately you packed it inside a GlobalScope.launch
again, which just puts that waiting in a background thread. Therefore it reaches the done
earlier then you expect and on my machine it didn't even print any hello
(but it could).
I assume you used launch
because join
can only be called from a coroutine or another suspending function? For your example it would have been sufficed to just add suspend
to main
, e.g.:
suspend fun main() {
val job = GlobalScope.launch { hello() }
job.join()
print("done")
}
or you could have used runBlocking
and wrap the main
with it, e.g.:
fun main() = runBlocking {
val job = launch { hello() }
job.join()
print("done")
}
Now the disclaimer... you may want to consult the following sources before continuing (if you didn't do already):
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With