What's the difference between executing some opera...
# coroutines
n
What's the difference between executing some operations in a
coroutineScope { }
vs. just executing them in the outer scope? Assuming the outer context has a regular
Job
.
b
The first option will suspend until all jobs launched inside complete
n
Wouldn't that happen anyway? E.g.
Copy code
suspendFun0()
suspendFun1()
withContext(otherContext) {
  suspendFun2()
}
vs.
Copy code
coroutineScope {
  suspendFun0()
  suspendFun1()
  withContext(otherContext) {
    suspendFun2()
  }
}
In both cases I reach the end of the code when all ops have finished. Or get an exception if they fail. And since we have a regular
Job
in both cases, failure of any child will cancel everything else (just maybe in a different order), in both cases.
My feeling is that the point of
coroutineScope { }
is just to ensure that current job is a
Job()
(not supervised) so if you already know that, coroutineScope {} is useless. I can't tell whether this is the case from documentation though
b
Yes for this case, but consider another case:
Copy code
fun CoroutineScope.test1() {
  suspendFun1() //suspends
  launch { ... } //does not suspend
  suspendFun2() //executes basically immediately after suspendFun1() and suspends again 
  // returns after suspendFun2() resumes, does not wait for launched job
}

suspend fun test2() {
  coroutineScope {
    suspendFun1() //suspends
    launch { ... } //does not suspend
    suspendFun2() //executes basically immediately after suspendFun1() and suspends again
  } // suspends until all things inside resume, including launched job
  // returns after coroutineScope() resumes
}
a
coroutineScope
is used when you need access to a scope to launch other jobs, if you just need to launch a few suspending functions then you don’t need it indeed.
a
Sometimes you don't have an outer scope, e.g. in a suspend fun. If you want to use `launch`/`async` in a suspend fun, you have to use
coroutineScope
.
b
As docs state - coroutineScope & supervisorScope are to be used for parallel decomposition of work. It's a way to wrap multiple parallel coroutines that all need to complete before the block can move on
Let's say you want to print all values in massive list. To speed things up you could parallelise it:
Copy code
suspend fun printAllValues(list:List<Any>) {
  val workerCount = 5
  val chunks = list.chunk(list.size / 5)
  coroutineScope {
    repeat(workerCount) { i ->
      launch { // Prints each chunk in parallel
        chunks[i].forEach(::println)
      }
    }
  }
  // will return once ALL chunks are printed
}
n
Got it. Thank you guys. The example in the function documentation could be much better. It doesn't show any
launch
, it shows an
async
but it then uses
async.await()
so basically makes it look like a regular scope.
e
You can always open an issue in the Kotlin coroutines repo to request documentation enhancements: https://github.com/Kotlin/kotlinx.coroutines/ Or just contribute yourself!
n
I'm pretty busy with my
Job
🙂 but thanks for helping