Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Kotlin协程调用阻塞函数?_Kotlin_Kotlin Coroutines - Fatal编程技术网

如何使用Kotlin协程调用阻塞函数?

如何使用Kotlin协程调用阻塞函数?,kotlin,kotlin-coroutines,Kotlin,Kotlin Coroutines,我想使用Kotlin协程来调用阻塞函数 例如,我希望有一个suspend函数,当对话框和网络库不提供suspend函数时,该函数将“阻塞”直到用户响应模式对话框,或者直到网络调用返回 我使用一个互斥体实现了它 例如,对于阻塞网络呼叫场景,我做了如下操作: class Connection { private val mutex = Mutex() public suspend fun receive(): ByteArray { mutex.lock()

我想使用Kotlin协程来调用阻塞函数

例如,我希望有一个suspend函数,当对话框和网络库不提供
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