The launch function returns an instance of the Job class, which means that a coroutine can be cancelled at any time. In this case, if we have a long-term operation in the finally block, JobCancellationException will be thrown.
The following example shows a case like this:
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch {
try {
delay(1000000)
} finally {
try {
println("start")
delay(1000)
println("end")
} catch (exception: Exception) {
exception.printStackTrace()
}
}
}
delay(500)
job.cancel()
job.join()
}
The following is the output:
kotlinx.coroutines.experimental.JobCancellationException: Job was cancelled normally; job=StandaloneCoroutine{Cancelling}@7f77b211
start
As you can see, the finally block can't be executed in a canceled coroutine and we can't release resources. We can deal with this using the withContext function:
withContext(NonCancellable) {
try {
println("start")
delay(1000)
println("end")
} catch (exception: Exception) {
exception.printStackTrace()
}
}
The output now looks as follows:
start
end
The withContext function invokes the passed suspended block with a given coroutine context.