knthmn
11/26/2021, 2:59 PMinterface Worker {
// does the work, throws Exception promptly if cancel() is called
fun doWork()
fun cancel()
}
What is the best way to convert it into suspend fun Worker.doWorkCancellable() ? Preferably something that works with a single threaded executor.Joffrey
11/26/2021, 3:20 PMdoWork does the work in a thread, is it asynchronous? Or does it block the current thread while doing so?knthmn
11/26/2021, 3:21 PMknthmn
11/26/2021, 3:29 PMsuspend fun Worker.doWorkCancellable(): Unit = coroutineScope {
launch { doWork() }
// using another dispatcher so if the original dispatcher is single threaded, it still cancels
withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
try {
awaitCancellation()
} finally {
cancel()
}
}
}Joffrey
11/26/2021, 3:34 PMdoWork is blocking, you have to use another thread to call cancel().Joffrey
11/26/2021, 3:38 PMdoWorkCancellable cannot finish normally (with your current implementation)Nick Allen
11/27/2021, 1:39 AMNick Allen
11/27/2021, 1:41 AM<http://Dispatchers.IO|Dispatchers.IO> and the suspending awaitCancellation() can just run as-is.Nick Allen
11/27/2021, 1:45 AMsuspendCancellableCoroutine when looking to convert existing APIs to coroutines:
suspend fun Worker.awaitWork() {
withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
suspendCancellableCoroutine<Unit> { cont ->
cont.invokeOnCancellation {
this@awaitWork.cancel()
}
try {
doWork()
} catch (e: Exception) {}
cont.resume(Unit)
}
}
}knthmn
11/27/2021, 11:22 AMsuspendCancellableCoroutine() meant to finish quickly and not block? In all the examples of suspendCancellableCoroutine() , the block returns immediately after setting up some callback. Is there any problem using it your way?Nick Allen
11/28/2021, 4:23 AMsuspendCancellableCoroutine will block. That's why I used <http://Dispatchers.IO|Dispatchers.IO>.