https://kotlinlang.org logo
#coroutines
Title
# coroutines
n

natario1

04/29/2021, 4:09 PM
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
With both attempts here in case you want to play with it https://pl.kotl.in/401iKiPLy second one works
4 Views