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