Sebouh Aguehian
10/11/2019, 1:21 PMSebouh Aguehian
10/11/2019, 1:21 PMfun main() {
val job = GlobalScope.launch(Dispatchers.Main) {
println("This is executed before toBeCancelled")
toBeCancelled()
println("This is executed after toBeCancelled")
}
}
suspend fun toBeCancelled() {
withContext(EmptyCoroutineContext) {
coroutineContext[Job]!!.cancel()
println("This is executed before the delay")
delay(2000)
println("This is executed after the delay")
}
}
This is executed before toBeCancelled
This is executed before the delay
How come “This is executed after toBeCancelled” is not printed? My understanding is that withContext would create a child job, and calling coroutineContext[Job]!!.cancel() should only cancel that child job. How come it is impacting the parent?streetsofboston
10/11/2019, 1:32 PMwithContext { ... } throws a CancellationException. This bubbles up to the caller.streetsofboston
10/11/2019, 1:34 PMsuspend fun toBeCancelled() {
try {
withContext(EmptyCoroutineContext) {
coroutineContext[Job]!!.cancel()
println("This is executed before the delay")
delay(2000)
println("This is executed after the delay")
}
} catch (e: Throwable) { println("withContext threw exception $e"); throw e }
}streetsofboston
10/11/2019, 1:35 PMthrow e from the catch clause will eat that cancellation exception and “This is executed after toBeCancelled” will be printed out (note: Don’t eat/forget-to-rethrow CancellationExceptions. It can break the Structured Concurrency!)Sebouh Aguehian
10/11/2019, 1:36 PMwithContext? The following doesn’t cancel the parent.
fun main() {
val job = GlobalScope.launch(Dispatchers.Main) {
println("This is executed before toBeCancelled")
launch {
coroutineContext[Job]!!.cancel()
println("This is executed before the delay")
delay(2000)
println("This is executed after the delay")
}.join()
println("This is executed after toBeCancelled")
}
}Sebouh Aguehian
10/11/2019, 1:36 PMstreetsofboston
10/11/2019, 1:37 PMlaunch { ... }.join() is not like withContexstreetsofboston
10/11/2019, 1:37 PMwithContext is more like async { .... }.await(). It returns the value of its lambda.Sebouh Aguehian
10/11/2019, 1:38 PMSebouh Aguehian
10/11/2019, 1:39 PMstreetsofboston
10/11/2019, 1:40 PMlaunch will never throw an exception. A call to join won’t either. A launch will cause the CoroutineScope’s CoroutineExceptionHandler to be called.
a call to async will never throw an exception either, but a call to await will throw an exception (if there was one thrown by the lambda of async)streetsofboston
10/11/2019, 1:41 PMwithContext, like async { ...}.await(), re-throws any exception thrown in its lambda. And that exception can be a CancellationException (caused by a call to cancel somewhere)streetsofboston
10/11/2019, 1:43 PMSebouh Aguehian
10/11/2019, 1:44 PMlaunch, that bubble up right?Sebouh Aguehian
10/11/2019, 1:45 PMSebouh Aguehian
10/11/2019, 1:45 PMstreetsofboston
10/11/2019, 1:47 PMlaunch will be handled by the CoroutineScope’s CoroutineExceptionHandler (CEH).
If that exception is a CancellationException, nothing really will happen, except for the CoroutineScope getting cancelled (unless a SupervisorScope is used). If it is not a CancelationException, depending whether you have a CEH installed or not and the implementation of your CEH and the implementation of your app’s ‘uncaught-exception-handler’, your app may crash.Sebouh Aguehian
10/11/2019, 1:53 PMfun main() {
val job = GlobalScope.launch(Dispatchers.Main) {
println("This is executed before toBeCancelled")
try {
launch {
throw Exception("shiiiii")
}.join()
} catch (e: Exception) {
println (e)
}
println("This is executed after toBeCancelled")
}
}
I’m getting:
This is executed before toBeCancelled
JobCancellationException: StandaloneCoroutine is cancelling; caused by Exception: shiiiii; job=StandaloneCoroutine{Cancelling}@11
This is executed after toBeCancelled
Exception: shiiiii
Seems like I’m able to catch it outside the launch?Pablichjenkov
10/11/2019, 2:07 PMcoroutineContext[Job]!!.cancel()
inside withContext will return the parents job. withContext switches Context but I don't think it creates a new child Job().Sebouh Aguehian
10/11/2019, 2:08 PMPablichjenkov
10/11/2019, 2:08 PM