我还没有完全掌握 Kotlin 协程。
基本上,我希望一个协程在执行之前等待任何先前的调用完成。以下代码似乎有效。但它在做我认为它正在做的事情吗?
private var saveJob: Job? = null
fun save() {
saveJob = someScope.launch {
saveJob?.join()
withContext(Dispatchers.IO) {
// suspending database operation
}
}
}
据我所知,代码正在做我想做的事。但真的是这样吗?
请记住,launch
ed代码与其外部的代码并发。这意味着您编写的内容具有争用条件:当您尝试join()
新作业时,外部代码可能已经将新作业分配给saveJob
,从而导致死锁。
我想你想要的是save
后台触发一个操作,操作本身会从其他地方提取所有数据来保存。您可能不想要save
作业的队列,只需确保在调用save()
时保存所有内容即可。如果您稍早调用save
,并且新的保存作业尚未启动,则可以将这两个调用合并为单个save
操作。
此外,您说您有一个挂起的数据库操作。挂起代码不属于IO
调度程序,仅当您必须同时执行许多阻塞操作时,调度程序才存在。
所有人都告诉我我建议使用演员:
val actor = someScope.actor<Unit>(capacity = CONFLATED) {
// suspending database operation
}
fun save() = someScope.launch {
actor.send(Unit)
}
基本上没有错。尽管我建议像在协程之外编程一样强制进行。将响应保存在变量中将确保下一行在第一行的响应之前不会执行:
scope.launch(someDispatcher){
val dataFromDelayingCode = getDelayingData()
if(delayingData.isFinished){
}
}