gpt4 book ai didi

concurrency - 协程:List 中的延迟操作按顺序运行。

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

我有一个 List执行下载的参数。
我将该列表的元素映射到 Deferred执行下载;然后,forEach列表的元素,我称之为 await ,但显然下载是按顺序执行的。

这是我的功能:

suspend fun syncFiles() = coroutineScope {
remoteRepository.requiredFiles()
.filter { localRepository.needToDownload( it.name, it.md5 ) }
.map { async { downloader( it ) } }
.forEach { deferredResult ->

when ( val result = deferredResult.await() ) {
is DownloadResult.Layout -> localRepository.storeLayout( result.content )
is DownloadResult.StringR -> localRepository.storeFile( result )
}
}
}

这是我的测试:
private val useCase = SyncUseCaseImpl.Factory(
mockk { // downloader
coEvery { this@mockk.invoke( any() ) } coAnswers { delay(1000 );any() }
},
...
).newInstance()

@Test
fun `syncFiles downloadConcurrently`() = runBlocking {
val requiredFilesCount = useCase.remoteRepository.requiredFiles().size
assert( requiredFilesCount ).isEqualTo( 3 )

val time = measureTimeMillis {
useCase.syncFiles()
}

assert( time ).isBetween( 1000, 1100 )
}

这是我的结果: expected to be between:<1000L> and <1100L> but was:<3081L>
我觉得很奇怪,因为这两个虚拟测试正确完成,也许我遗漏了一些东西(?)
@Test // OK
fun test() = runBlocking {
val a = async { delay(1000 ) }
val b = async { delay(1000 ) }
val c = async { delay(1000 ) } ​
val time = measureTimeMillis {
a.await()
b.await()
c.await()
} ​
assert( time ).isBetween( 1000, 1100 )
} ​

@Test // OK
fun test() = runBlocking {
val wasteTime: suspend () -> Unit = { delay(1000 ) }
suspend fun wasteTimeConcurrently() = listOf( wasteTime, wasteTime, wasteTime )
.map { async { it() } }
.forEach { it.await() } ​
val time = measureTimeMillis {
wasteTimeConcurrently()
} ​
assert( time ).isBetween( 1000, 1100 )
}

最佳答案

问题出在 mockk
如果您查看 coAnswer 的代码函数你会发现这个(API.kt + InternalPlatformDsl.kt):

infix fun coAnswers(answer: suspend MockKAnswerScope<T, B>.(Call) -> T) = answers {
InternalPlatformDsl.runCoroutine {
answer(it)
}
}

runCoroutine看起来像这样。
actual fun <T> runCoroutine(block: suspend () -> T): T {
return runBlocking {
block()
}
}

如您所见, coAnswer是一个非挂起函数,并以 runBlocking 开始一个新的协程.

让我们看一个例子:
val mock =  mockk<Downloader> {
coEvery {
this@mockk.download()
} coAnswers {
delay(1000)
}
}

val a = async {
mock.download()
}

mockk执行 coAnswer -block ( delay()),它启动一个人工协程作用域,执行给定的 block 并等待(阻塞当前线程: runBlocking)直到这个 block 完成。所以答案 block 只在 delay(1000) 之后返回已完成。

表示从 coAnswer 运行的所有协程依次执行。

关于concurrency - 协程:List 中的延迟操作按顺序运行。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53238428/

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