-
Notifications
You must be signed in to change notification settings - Fork 23
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
withContext
ordelay
in 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
withContext
ordelay
, 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