Reputation: 3
val parentScope = CoroutineScope(Dispatchers.Main)
parentScope.launch {
try{
launch{ // child scope
//code ....
throw CustomError("error", null)
}
} catch(cause: CustomError){
// It did not get executed
}
}
In the above code snippet the app got crash. The exception thrown from it is not caught into the parentScope catch block.
But if we replace the above childScope with
supervisorScope or
coroutineScope or
withContext or
runBlocking
it catught the exception.
parentScope.launch {
try{
supervisorScope {
//code
throw CustomError("error", null)
}
} catch(cause: CustomError){
// It get execute when withContext/supervisorScope
}
}
Why exception thrown from child scope(launch) is not caught by parent catch block?
Exception:
FATAL EXCEPTION: DefaultDispatcher-worker-1
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Upvotes: 0
Views: 465
Reputation: 28462
Disclaimer: this question has been edited which greatly affected the answer. Original answer is below.
launch()
is used to run the code asynchronously, in a separate coroutine or in the background. CustomError
is not really thrown from within try...catch
. Code which invokes launch()
doesn't even wait for it to start executing - it only schedules the code to be executed and then immediately progress further.
This is similar to starting a new thread. If the thread throws, you can't catch this in the code that created or started the thread. Code that started the thread and the code inside the thread are running in two separate execution contexts.
All other functions you mentioned (coroutineScope()
, runBlocking()
, etc.) run synchronously - they wait for the block of code to be executed, they wait for its result. Inner block of code runs inside the same execution context as the outer one. For this reason exceptions could be propagated as usual.
Original answer:
In your first example there is really no parent-child relationship. Both parentScope
and childScope
are created separately and they run independently of each other. Simply because you put one code block inside another doesn't mean they are in any way related.
withContext()
is different, it uses the current scope (parentScope
) to execute the code.
In other words: whenever you use someScope.launch()
this is like explicitly asking to switch to entirely different execution context.
Upvotes: 0