guys, I am confused ``` coroutineScope(UI) { ...
# coroutines
m
guys, I am confused
Copy code
coroutineScope(UI) {
        try {
            val a = async(IO) {
                delay(1000)
                println("Done after delay")
            }
            val b = async(IO) { throw Exception() }
            awaitAll(a, b)
        } catch (e: Exception) {
            println("Caught $e")
        }
    }
^ why does this crash my application? why is the exception not propagated to the outer
try & catch
?
1
g
Because coroutineScope failed (because one of coroutines inside failed)
m
but why can't I just handle this in try and catch?
g
this is required to avoid leaked coroutines
no, this is not that you cannot catch, try/catch also works
this is justt how coroutineScope works
if some coroutine inside failed, coroutineScope also fails
you need supervisorScope, if you want to manage it manually
m
okay wait, give me some time to read this, I just want to understand why this can't be a default behaviour like RX, if one of the child job fails, that the exception is propagated to the other try catch, it crashes application only if it is not handled
g
Rx doesn’t have structured concurrency, so there is no direct analogy
it’s just a different level of exceptions. One handled inside of coroutine, another is thrown because child coroutine is crashed in coroutine scope, there is special param in Job that propagate exception to parent (which is false for SupervisorJob)
also, in general I don’t see why you need coroutineScope in this particular example
l
@mingkangpan Here's your code, fixed:
Copy code
try {
    coroutineScope {
        val a = async(<http://Dispatchers.IO|Dispatchers.IO>) {
            delay(1000)
            println("Done after delay")
        }
        val b = async(<http://Dispatchers.IO|Dispatchers.IO>) {
            throw Exception()
        }
        awaitAll(a, b)
    }
} catch (e: Exception) {
    println("Caught $e")
}
m
thanks, if there any difference here?
Copy code
scope(IO) {
   async { }
   async {  }
}
vs
Copy code
scope {
   async(IO) { }
   async(IO) {  }
}
g
No
I'm still not sure that you need coroutineScope, only if it's some standalone suspend function, but in this case just swallow exception is not good.
m
think that delay is in RL some IO request and exception if IO request fails I want both requests executed in parallel, the speed things up my main scope is Main thread to update the UI
g
See, it's fine to use coroutineScope if you have some function that launches a few coroutines inside and return only when all of them are finished. I'm According to your use case it should be fine to use coroutineScope, just was not originally clear from your first example