Ejecute dos rutinas Kotlin dentro de la rutina en paralelo

2 minutos de lectura

Tengo dos funciones de suspensión:

suspend fun sendData() : Boolean 

suspend fun awaitAcknowledge() : Boolean

y quiero envolverlos en una tercera función de suspensión en la que deben ejecutarse en paralelo y quiero calcular el resultado final teniendo ambos valores de retorno:

suspend fun sendDataAndAwaitAcknowledge() : Boolean {
    // TODO execute both in parallel and compare both results
}

Sin embargo, si lo escribo así,

suspend fun sendDataAndAwaitAcknowledge() : Boolean {
    val sendResult = sendData()
    val receiveAck = awaitAcknowledge()
}

las funciones se ejecutarán en orden serial, lo cual no funcionará en mi caso.

Viniendo de RxJava, me gustaría lograr algo como el zip operador:

Single.zip(awaitAcknowledge(), sendData(), {receiveAck, sendResult -> ...})

¿Cómo puedo hacer esto con Coroutines?

Puedes usar awaitAll para ese propósito:

import kotlinx.coroutines.*

suspend fun sendDataAndAwaitAcknowledge() = coroutineScope {
    awaitAll(async {
        awaitAcknowledge()
    }, async {
        sendData()
    })
}

fun sendData() = true

fun awaitAcknowledge() = false

fun main() {
    runBlocking {
        println(sendDataAndAwaitAcknowledge()) // [false, true]
    }
}

  • ¿Es posible ejecutar todas las funciones al mismo tiempo sin un retraso de milisegundos?

    – RaJ

    28 de marzo a las 7:26

Usar como este patrón:

    suspend fun sendDataAndAwaitAcknowledge() {
     val one = async { sendData() }
     val two = async { awaitAcknowledge() }
     println("The result is ${one.await() + two.await()}")
    }

como puede ver, se llaman dos funciones de suspensión en la tercera y, en paralelo, la tercera función de suspensión esperará a que las otras dos terminen sus tareas.

  • no puedes simplemente usar async. Necesitas un ámbito de rutina para ello.

    – Andrei Tanana

    12 de agosto de 2019 a las 7:39

  • @AndreiTanana revisa el enlace. kotlinlang.org/docs/reference/coroutines/…

    usuario3089483

    12 de agosto de 2019 a las 7:55


  • este es el código completo de este ejemplo github.com/kotlin/kotlinx.coroutines/blob/master/… usa runBlocking alcance

    – Andrei Tanana

    12 de agosto de 2019 a las 8:03

  • Hmm, cuando trato de implementar de esta manera, obtengo unresolved reference sobre el async palabra clave. Sin embargo, no recibo una sugerencia de importación de Android Studio.

    – Cristóbal

    12 de agosto de 2019 a las 8:48

  • El async que se utiliza aquí es una importación estática de GlobalScope, que no es una gran cosa para usar. Async debe lanzarse desde un ámbito de corrutina más granular.

    – afollestad

    19 de mayo de 2022 a las 0:47


¿Ha sido útil esta solución?