https://kotlinlang.org logo
#coroutines
Title
# coroutines
m

mingkangpan

01/18/2019, 9:01 AM
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

gildor

01/18/2019, 9:02 AM
Because coroutineScope failed (because one of coroutines inside failed)
m

mingkangpan

01/18/2019, 9:03 AM
but why can't I just handle this in try and catch?
g

gildor

01/18/2019, 9:03 AM
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

mingkangpan

01/18/2019, 9:13 AM
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

gildor

01/18/2019, 9:15 AM
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

louiscad

01/18/2019, 11:08 AM
@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

mingkangpan

01/18/2019, 11:13 AM
thanks, if there any difference here?
Copy code
scope(IO) {
   async { }
   async {  }
}
vs
Copy code
scope {
   async(IO) { }
   async(IO) {  }
}
g

gildor

01/18/2019, 11:14 AM
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

mingkangpan

01/18/2019, 11:54 AM
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

gildor

01/20/2019, 11:38 AM
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
5 Views