-
Notifications
You must be signed in to change notification settings - Fork 24
Significance of ensureActive co‐operative cancellation
Devrath edited this page Jan 14, 2024
·
2 revisions

- Say you have launched a coroutine and that coroutine calls a normal suspending function.
- Now say this normal suspending function does not have a
withContextordelayin it but does a long iterative call that takes time. - Now if we cancel the scope, the scope will get canceled but since the suspending function is called from it and it does not have
withContextordelay, It will continue the execution - This indicates that the suspending function called is not cooperative
- Suspending functions are just normal functions but have a suspending modifier in addition that ensures that anything that calls it from. another suspending function.
- We can explicitly check as below and throw a cancellation exception
if(currentCoroutineContext().isActive){
throw CancellationException("Exception Occurred")
}- Or we can call
currentCoroutineContext().ensureActive()which does the above same check
- Because of this if the coroutine that called the suspending function is cancelled, This automatically cancelled because of this check
- The above modifiers help internally check that if the coroutine is active or not
Code
class EnsureActiveDemoVm @Inject constructor( ) : ViewModel() {
private var job: Job? = null
fun startWithThreadSleep() {
job = CoroutineScope(Dispatchers.Default).launch {
startSuspendWithThreadSleep()
}
}
private suspend fun startSuspendWithThreadSleep() {
try {
repeat(10) { index ->
currentCoroutineContext().ensureActive()
// Simulate some work
Thread.sleep(500)
// Check if the coroutine has been canceled
if (!currentCoroutineContext().isActive) {
println("Coroutine canceled at index $index")
}
// Continue with the main logic
println("Working at index $index")
}
// Additional logic after the loop
println("Coroutine completed")
} catch (e: CancellationException) {
// Handle cancellation-specific tasks
println("Coroutine canceled")
}
}
fun cancel(){
job?.cancel()
}
}Output: Here we pressed cancel when the control was at index 3
Working at index 0
Working at index 1
Working at index 2
Coroutine canceled at index 3
Working at index 3
Coroutine canceled