69

I have two suspend functions:

suspend fun sendData() : Boolean 

suspend fun awaitAcknowledge() : Boolean

and I want to wrap them in a third suspend function in which they should be executed in parallel and I want to calculate the final result by having both return values:

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

However, if I write it like that,

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

the functions will be executed in a serial order, which will not work in my case.

Coming from RxJava, I would like to achieve something like the zip operator:

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

How can I do this with Coroutines?

2 Answers 2

65

You can use awaitAll for that purpose:

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]
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

It is possible to execute all functions at the same time without a milliseconds delay?
15

This is the general pattern:

suspend fun sendDataAndAwaitAck() = coroutineScope {
  val one = async { sendData() }
  val two = async { awaitAck() }
  println("The result is ${one.await()}, ${two.await()}")
}

The two suspending functions (sendData and awaitAck) are called from within another suspending function (sendDataAndAwaitAck). They could potentially run in parallel, depending on the environment and CPU setup. The outer suspending function will wait for the two inner functions to finish their tasks before proceeding.

Note 1: async is available only in a Coroutine Scope.

Note 2: if you don't want the whole scope to fail when one of the child coroutines fails, you should use supervisorScope instead.

5 Comments

you cannot just use async. You need coroutine scope for it
@AndreiTanana check the link. kotlinlang.org/docs/reference/coroutines/…
this is the full code of this example github.com/kotlin/kotlinx.coroutines/blob/master/… it uses runBlocking scope
Hmm, when I try to implement in this way, I get unresolved reference on the async keyword. However, I don't get an import suggestion from Android Studio.
The async being used here is a static import from GlobalScope, which is not a great thing to use. Async should be launched off of a more granular coroutine scope.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.