Pablo Fernandez
Pablo Fernandez

Reputation: 105220

Proper way of dealing with blocking code using Kotling coroutines

Suppose I have a blocking function because of some third party library. Something along these lines:


fun useTheLibrary(arg: String): String {
   val result = BlockingLibrary.doSomething(arg)
   return result
}

Invocations to BlockingLibrary.doSomething should run on a separate ThreadPoolExecutor.

What's the proper way (assuming there is a way) of achieving this with kotlin?

Note: I've read this thread but seems pretty outdated

Upvotes: 10

Views: 3479

Answers (1)

Tenfour04
Tenfour04

Reputation: 93609

If the blocking code is blocking because of CPU use, you should use Dispatchers.Default. If it is network- or disk-bound, use Dispatchers.IO. You can make this into a suspending function and wrap the blocking call in withContext to allow this function to properly suspend when called from a coroutine:

suspend fun useTheLibrary(arg: String): String = withContext(Dispatchers.Default) {
   BlockingLibrary.doSomething(arg)
}

If you need to use a specific ThreadPoolExecutor because of API requirements, you can use asCoroutineDispatcher().

val myDispatcher = myExecutor.asCoroutineDispatcher()

//...

suspend fun useTheLibrary(arg: String): String = withContext(myDispatcher) {
   BlockingLibrary.doSomething(arg)
}

If your library contains a callback-based way to run the blocking code, you can convert it into a suspend function using suspendCoroutine() or suspendCancellableCoroutine(). In this case, you don't need to worry about executors or dispatchers, because it's handled by the library's own thread pool. Here's an example in the Retrofit library, where they convert their own callback-based API into a suspend function.

Upvotes: 11

Related Questions