Eugen Martynov
01/26/2021, 5:28 PMMarc Knaup
01/26/2021, 5:33 PMcoroutineContext.job.invokeOnCompletion(onCancelling = true) { … }
🤔Adam Powell
01/26/2021, 6:19 PMsuspendCancellableCoroutine { continuation ->
val cancellable = startAsyncWork(..., Callback { result ->
continuation.resume(result)
})
invokeOnCancellation {
cancellable.cancel()
}
}
Marc Knaup
01/26/2021, 6:21 PMAdam Powell
01/26/2021, 6:22 PM@InternalCoroutinesApi
public fun invokeOnCompletion(
onCancelling: Boolean = false,
invokeImmediately: Boolean = true,
handler: CompletionHandler): DisposableHandle
internal
, but not really experimental in the sense of, "this is on track to become public API in the future" eitherbezrukov
01/26/2021, 6:24 PMMarc Knaup
01/26/2021, 6:25 PMAdam Powell
01/26/2021, 6:26 PMsuspendCancellableCoroutine
and CancellableContinuation.invokeOnCancellation
. Using try/catch means your continuation needs to resume on its dispatcher before the cleanup code runs. Generally there's no reason to wait for that unless cancellation requires you to be on a particular dispatcher to perform itbezrukov
01/26/2021, 6:31 PMsuspendCancellableCoroutine
works for "cold" Closeable (disposable/future/whatever). If you need to close hot closeable once job cancelled, suspendCancellableCoroutine won't work, because it checks cancellation beforelouiscad
01/27/2021, 8:12 PMEugen Martynov
01/29/2021, 9:24 AMbezrukov
01/29/2021, 9:42 AMfun CoroutineScope.invokeOnCancel(block: () -> Unit) {
launch(start = CoroutineStart.UNDISPATCHED) {
try {
suspendCancellableCoroutine<Unit> { }
} finally {
block()
}
}
}
then do
scope.invokeOnCancel {
// cleanup code here
}
Eugen Martynov
01/29/2021, 10:00 AMsuspendCancellableCoroutine
bezrukov
01/29/2021, 10:18 AMsuspendCancellableCoroutine<Unit> { }
can be changed to delay(Long.MAX_VALUE)
if it more descriptivewhere is callback put, on which thread it operated.If the scope was already cancelled, callback will be invoked immediately on the caller thread. Otherwise it will be invoked on scope's dispatcher. If you want it to be invoked on scope's dispatcher (even if it's already cancelled), use
CoroutineStart.ATOMIC