使用 Kodling 协程处理阻塞代码的正确方法

Pab*_*dez 10 nonblocking blocking kotlin kotlin-coroutines

假设我由于某些第三方库而具有阻塞功能。沿着这些思路:


fun useTheLibrary(arg: String): String {
   val result = BlockingLibrary.doSomething(arg)
   return result
}
Run Code Online (Sandbox Code Playgroud)

对 的调用BlockingLibrary.doSomething应该在单独的ThreadPoolExecutor.

使用 kotlin 实现这一目标的正确方法是什么(假设有一种方法)?

注意:我已经读过这篇文章,但似乎已经过时了

Ten*_*r04 10

如果阻塞代码由于 CPU 使用而阻塞,则应该使用Dispatchers.Default. 如果它是网络或磁盘绑定的,请使用Dispatchers.IO. 您可以将其放入挂起函数并将阻塞调用包装起来withContext,以允许该函数在从协程调用时正确挂起:

suspend fun useTheLibrary(arg: String): String = withContext(Dispatchers.Default) {
   BlockingLibrary.doSomething(arg)
}
Run Code Online (Sandbox Code Playgroud)

ThreadPoolExecutor如果由于 API 要求而需要使用特定的,则可以使用asCoroutineDispatcher().

val myDispatcher = myExecutor.asCoroutineDispatcher()

//...

suspend fun useTheLibrary(arg: String): String = withContext(myDispatcher) {
   BlockingLibrary.doSomething(arg)
}
Run Code Online (Sandbox Code Playgroud)

如果您的库包含基于回调的方式来运行阻塞代码,您可以使用suspendCoroutine()或将其转换为挂起函数suspendCancellableCoroutine()。在这种情况下,您不需要担心执行程序或调度程序,因为它是由库自己的线程池处理的。这是 Retrofit 库中的一个示例,其中他们将自己的基于回调的 API 转换为挂起函数。