gpt4 book ai didi

Kotlin:如何在没有 runBlocking 的情况下等待非挂起的协程?

转载 作者:行者123 更新时间:2023-12-02 13:34:40 27 4
gpt4 key购买 nike

编辑 2:我想我误解了文档。我读:

runBlocking

This function should not be used from a coroutine. It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in main functions and in tests.



意思是我不应该使用 runBlocking()除了 main或测试。但我现在意识到我读错了,特别是这部分:

It is designed to bridge regular blocking code to libraries that are written in suspending style



所以看起来 runBlocking 应该在这个场景中使用。

但是,我认为我应该完全理解上下文的主题,以查看在这种情况下哪些上下文最适合传递给 runBlocking:
return runBlocking(???????) {
job1.await() + job2.await()
}

编辑:显然,我对这个问题的措辞很糟糕,因为所有回答它的尝试都错过了我提出的实际问题和约束。所以让我们尝试不同的方法......

这有效:
fun doSomething(): Int {
val job1 = GlobalScope.async { calculateSomething() }
val job2 = GlobalScope.async { calculateSomething() }
return runBlocking {
job1.await() + job2.await()
}
}

suspend fun calculateSomething(): Int {
delay(1000L)
return 13
}

suspend fun calculateSomethingElse(): Int {
delay(2000L)
return 19
}

我的问题是:无论如何我可以达到相同的结果:
  • 使用 runBlocking()根本。
  • 车削doSomething()suspend功能。

  • ?

    换句话说:有什么可以代替 ?????? 的吗?使以下工作?
    fun doSomething(): Int {
    val job1 = GlobalScope.async { calculateSomething() }
    val job2 = GlobalScope.async { calculateSomething() }
    return ????????? {
    job1.?????() + job2.?????()
    }
    }

    suspend fun calculateSomething(): Int {
    delay(1000L)
    return 13
    }

    suspend fun calculateSomethingElse(): Int {
    delay(2000L)
    return 19
    }


    我有一个小的实用程序方法,它运行任何给定的外部命令并返回其输出(即围绕 Java Process API 的小包装器):
    class RunningCommand(private val proc: Process) {

    fun waitFor(): String {
    proc.outputStream.close()

    var output = ""
    val outputRdr = thread { output = proc.inputStream.bufferedReader().use { it.readText() } }
    var error = ""
    val errorRdr = thread { error = proc.errorStream.bufferedReader().use { it.readText() } }

    proc.waitFor()

    outputRdr.join()
    errorRdr.join()

    if (proc.exitValue() != 0) {
    throw RuntimeException("Command returned non-zero status: $output$error")
    }

    return output
    }
    }

    此代码正常工作。但是,它为每个命令执行创建了两个额外的线程。我想通过切换到协程来避免这种情况。我能够做到这一点,但我不得不使用 runBlocking :
    class RunningCommand(private val proc: Process) {

    fun waitFor(): String {
    proc.outputStream.close()

    var output = ""
    val outputRdr = GlobalScope.async { output = proc.inputStream.bufferedReader().use { it.readText() } }
    var error = ""
    val errorRdr = GlobalScope.async { error = proc.errorStream.bufferedReader().use { it.readText() } }

    proc.waitFor()

    runBlocking {
    outputRdr.await()
    errorRdr.await()
    }

    if (proc.exitValue() != 0) {
    throw RuntimeException("Command returned non-zero status: $output${error}")
    }

    return output
    }
    }

    此代码也有效,但我读到 runBlocking只能用于 main()方法和测试,即不打算以这种方式使用。看看它的实现,它看起来很可怕,而且确实看起来像是人们不想从某个实用程序方法重复调用的东西。

    所以我的问题是:我还应该如何弥合阻塞代码和协程之间的差距?或者换句话说,等待 suspend 的正确方法是什么?来自非 suspend 的函数代码?

    或者仅仅是我的设计是错误的,并且要在任何地方使用协程,我需要制作 main()方法 runBlocking并且基本上总是在某个协程范围内?

    最佳答案

    对于 future 和我犯同样错误的旅行者 - runBlocking不仅可以在 main 中使用也可以/测试 - 还有:

    It is designed to bridge regular blocking code to libraries that are written in suspending style


    不知何故,我的印象是,仅用于某些库函数是邪恶的,但事实并非如此。

    关于Kotlin:如何在没有 runBlocking 的情况下等待非挂起的协程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59528802/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com