首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Kotlin协同器调用阻塞函数?

如何使用Kotlin协同器调用阻塞函数?
EN

Stack Overflow用户
提问于 2020-10-11 16:25:09
回答 2查看 2.6K关注 0票数 3

我想用Kotlin协同器来调用阻塞函数。

例如,我希望有一个挂起函数,它将“阻塞”直到用户响应一个模态对话框,或者直到一个网络调用返回时,当对话框和网络库不提供suspend函数时。

我使用Mutex实现了它。

例如,对于阻塞网络调用场景,我执行了如下操作:

代码语言:javascript
复制
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将阻塞流“转换”为协同流的角度来看:

  1. 有什么标准或更好的方法来做到这一点吗?
  2. 除了网络或性能之外,你认为我的方法有什么坏处吗?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-11 16:56:14

你可以这样做:

代码语言:javascript
复制
suspend fun receive(): ByteArray {
    return withContext(Dispatchers.IO) {
        val buf = ByteArray(42)
        sock.getInputStream().read(buf, 0, 42) // blocking
        buf
    }
}

从您的Activity中调用它为:

代码语言:javascript
复制
lifecycleScope.launch{
    withContext(Dispatchers.Main) {
        //showLoading
        val result = receive()
        //hideloading
    }
}

接收函数将在IO dispatcher (即designed for offloading blocking IO tasks to a shared pool of threads )中运行,请参阅有关dispatcher 这里的更多信息。

票数 3
EN

Stack Overflow用户

发布于 2020-10-11 16:55:18

标准的方法是使用IO调度器,它被设计为有大量线程池来处理阻塞操作(顾名思义,IO)。

代码语言:javascript
复制
withContext(Dispatchers.IO) {
    sock.getInputStream().read(buf, 0, 42)
}

这将暂停协同线,直到阻塞操作完成。

您的方法的缺点是,执行的顺序并不完全清楚,而且容易出现死锁。例如,如果阻塞调用抛出异常,互斥锁永远不会解锁,协同线将被卡住。此外,它还为每个阻塞操作创建新线程,而IO dispatcher则设计为重用一个线程池以避免这种开销。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64306381

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档