并行运行两个挂起函数,并在第一个函数返回时返回



我想运行以并行挂起函数,并在其中一个函数返回结果的速度越快时返回结果。我试着做了下面的事情,但我认为只有当他们两个都完成时,它才会回来,这需要太多时间,因为我在等待这两个。

val coroutineScope = CoroutineScope(Dispatchers.Main)
val a = coroutineScope.async {
a(context)
}
val b = coroutineScope.async {
b(context)
}
val results = listOf(a, b).awaitAll()
return if (results.any { it is RunSuccess }) {
...
} else {
...
}

有什么想法吗?

您可以按如下方式使用select

suspend fun doWork(): String = coroutineScope {
select<String> {
async { work1() }.onAwait { it }
async { work2() }.onAwait { it }
}.also {
coroutineContext.cancelChildren()
}
}

在本例中,返回一个String,但您可以根据需要更改它,这取决于您的work返回的内容。

如果你正在寻找更多的functional programming版本,你可以使用Arrow中的raceN

你在哪里有这种方法

public suspend inline fun <A, B> raceN(crossinline fa: suspend CoroutineScope.() -> A, crossinline fb: suspend CoroutineScope.() -> B): Either<A, B> =
raceN(Dispatchers.Default, fa, fb)

然后你把这个raceN方法称为

public suspend inline fun <A, B> raceN(
ctx: CoroutineContext = EmptyCoroutineContext,
crossinline fa: suspend CoroutineScope.() -> A,
crossinline fb: suspend CoroutineScope.() -> B
): Either<A, B> =
coroutineScope {
val a = async(ctx) { fa() }
val b = async(ctx) { fb() }
select<Either<A, B>> {
a.onAwait.invoke { Either.Left(it) }
b.onAwait.invoke { Either.Right(it) }
}.also {
when (it) {
is Either.Left -> b.cancelAndJoin()
is Either.Right -> a.cancelAndJoin()
}
}
}

Arrow fx有一个很好的方法,叫做raceN。

https://arrow-kt.io/docs/apidocs/arrow-fx-coroutines/arrow.fx.coroutines/race-n.html

最新更新