How to wait for all coroutines to finish?

11,893

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):

  1. Coroutine basics
  2. The reason to avoid GlobalScope by Roman Elizarov
  3. Concurrent coroutines - Concurrency is not parallelism by @s1m0nw1
Share:
11,893
nz_21
Author by

nz_21

Updated on June 15, 2022

Comments

  • nz_21
    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
    nz_21 about 5 years
    thanks 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
    Roland about 5 years
    ok... 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)