How do you make a long running, blocking function cancellable? E.g. with this third-party class:
Copy code
class Worker {
fun doWork()
fun cancelWork()
}
My attempt below (untested) doesn't look very good, I wonder if there's any better way.
Copy code
coroutineScope {
val job = launch {
while (isActive) {
delay(50)
}
}
job.invokeOnCompletion {
if (it is CancellationException) {
worker.cancelWork()
}
}
worker.doWork()
job.cancel()
}
a
araqnid
04/30/2021, 9:08 AM
you can access the current job inside
launch{}
as
coroutineContext[Job]
which would probably read better. I think with that there’s no need for the explicit cancel, just sth like:
Copy code
launch {
coroutineContext[Job]!!.invokeOnCompletion {
if (it is CancellationException) {
worker.cancelWork()
}
}
worker.doWork()
}
I also think that means there’s no need for the outer scope coroutine which is only there to cancel the inner one.
n
natario1
04/30/2021, 10:07 AM
Doesn't seem to work: https://pl.kotl.in/TEgYBGFYo
I think that invokeOnCompletion is not called until doWork() realizes it has been canceled, which won't happen because it's not a coroutine-based API. Unless we spawn a second coroutine