如何使用Kotlin协程调用阻塞函数?
我想使用Kotlin协程来调用阻塞函数 例如,我希望有一个suspend函数,当对话框和网络库不提供如何使用Kotlin协程调用阻塞函数?,kotlin,kotlin-coroutines,Kotlin,Kotlin Coroutines,我想使用Kotlin协程来调用阻塞函数 例如,我希望有一个suspend函数,当对话框和网络库不提供suspend函数时,该函数将“阻塞”直到用户响应模式对话框,或者直到网络调用返回 我使用一个互斥体实现了它 例如,对于阻塞网络呼叫场景,我做了如下操作: class Connection { private val mutex = Mutex() public suspend fun receive(): ByteArray { mutex.lock()
suspend
函数时,该函数将“阻塞”直到用户响应模式对话框,或者直到网络调用返回
我使用一个互斥体实现了它
例如,对于阻塞网络呼叫场景,我做了如下操作:
class Connection {
private val mutex = Mutex()
public suspend fun receive(): ByteArray {
mutex.lock()
val buf = ByteArray(42)
thread {
sock.getInputStream().read(buf, 0, 42) // blocking
mutex.unlock()
}
mutex.lock()
return buf
}
}
它起作用了
请忽略上述代码中与网络相关的问题(如错误处理、检查实际读取的字节数等)
还请忽略使用线程的性能方面(上面的专用线程只是为了示例)
从使用Mutex
将阻塞流“转换”为协同路由流的角度来看:
有没有一个标准或更好的方法来做到这一点
撇开网络或性能不谈——你认为我的方法有什么缺点吗
标准的方法是使用IO
调度程序,该调度程序设计为拥有大量线程池来处理阻塞操作(顾名思义,IO)
withContext(Dispatchers.IO){
sock.getInputStream().read(buf,0,42)
}
这将暂停协同路由,直到阻塞操作完成
您的方法的缺点是执行顺序不完全清楚,并且容易出现死锁。例如,如果阻塞调用抛出异常,互斥锁将永远不会解锁,协同路由将被卡住。此外,它还为每个阻塞操作创建新线程,而IO dispatcher设计为重用线程池以避免此成本。您只需执行以下操作:
suspend fun receive(): ByteArray {
return withContext(Dispatchers.IO) {
val buf = ByteArray(42)
sock.getInputStream().read(buf, 0, 42) // blocking
buf
}
}
从您的活动中调用它,如下所示:
lifecycleScope.launch{
withContext(Dispatchers.Main) {
//showLoading
val result = receive()
//hideloading
}
}
接收功能将在IO dispatcher中运行,设计用于将阻塞IO任务卸载到共享线程池
请参阅有关dispatchers的更多信息。您的意思是像runBlocking
之类的东西,它会阻塞线程,直到操作完成?@R'J看起来可以工作:)阻塞线程并不是真正的问题不过,推荐使用Kotlin协同程序处理问题的方法。它们的用途非常广泛,您可以在不使用块线程的情况下获得结果,因此我建议查看下面的人员编写的内容,特别是使用IO
dispatcher