julioromano
04/19/2024, 8:47 AMsuspendCancellableCoroutine
does the order of the call to invokeOnCancellation
matter?
I mean, is it best to call invokeOnCancellation
as first thing inside the suspendCancellableCoroutine
lambda?
Or is it the same if it's called as last instruction?bezrukov
04/19/2024, 9:59 AMbezrukov
04/19/2024, 10:03 AMZach Klippenstein (he/him) [MOD]
04/19/2024, 10:27 AMWhen the continuation is already cancelled, the handler is immediately invoked with the cancellation exception.So if you called it before setting a listener, you’d leak the listener. Also note that the cancellation callback is not dispatched, it’s ran synchronously, so if your listener api requires the listener be removed on a certain thread or to be otherwise synchronized you’d need to do that explicitly. Often more correct to remove the listener in a finally block around the suspension point, since that will be dispatched.
julioromano
04/19/2024, 11:01 AMbezrukov
04/19/2024, 11:10 AMtry {
suspendCancellableCoroutine { c -> ....
}
} finally {
cleanup()
}
bezrukov
04/19/2024, 11:13 AMjulioromano
04/19/2024, 11:16 AMsuspendCancellableCoroutine
?bezrukov
04/19/2024, 11:31 AMjulioromano
04/19/2024, 11:49 AMfinally
block will be dispatched.
What is it that actually makes it dispatched? Is it some special "magic" around this specific try/finally
case or is it just that any statement happening after a suspend call is dispatched separately?bezrukov
04/19/2024, 12:05 PMwithContext(Dispatchers.Main) {
print("A")
delay(300)
print("B")
}
or
withContext(Dispatchers.Main) {
print("A")
suspendCancellableCoroutine { .... }
print("B")
}
or
withContext(Dispatchers.Main) {
print("A")
withContext(Dispatchers.Default) { ... }
print("A")
}
Both A and B are guaranteed to be executed in Main thread. Nothing special about try/finally here, try/finally in this pattern is just to ensure resources are cleaned up in any case (successful completion / cancellation / error)
In contrast, in the following example:
withContext(Dispatchers.Main) {
print("A")
suspendCancellableCoroutine { cont ->
print("B")
cont.invokeOnCancellation { print("C") }
}
print("D")
}
C - might be invoked in random thread (typically in the thread that cancels the parent coroutine). A,B,D are executed in Mainjulioromano
04/19/2024, 1:45 PM