How to wait for all coroutines to finish?
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):
- Coroutine basics
- The reason to avoid GlobalScope by Roman Elizarov
- Concurrent coroutines - Concurrency is not parallelism by @s1m0nw1
![nz_21](https://lh3.googleusercontent.com/-VlOyJEUeeSc/AAAAAAAAAAI/AAAAAAAAAAA/AGDgw-jExBae7iJ2ALFtcMj_6BCoHGTMgw/mo/photo.jpg?sz=256)
nz_21
Updated on June 15, 2022Comments
-
nz_21 about 2 years
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?
-
nz_21 about 5 yearsthanks for the pointers :) My overall goal is to basically simulate goroutines with waitgroup. So an execution like this: ``` do_parallelel_operation(); add(a,b); wait_until_parallel_op_is_completed();``` I guess what I could do is, capture the suspend context in which the par operation is invoked, then ``join()``` the job in the same context when I want to "wait".
-
Roland about 5 yearsok... I somehow missed the "go part"... sorry for that... I don't know what "sync.WaitGroup" is actually doing and I am not so sure whether what you have shown so far in Kotlin is coming close to that... that's also why I can't really say anything about your comment now... but.. I think the linked documentation will get you to your answer rather soon... maybe you are looking for context and dispatchers? (at least it seems it has similar samples to your problem)