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>
.