让协程等待先前的呼叫 [英] Having coroutine wait for previous calls

查看:79
本文介绍了让协程等待先前的呼叫的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我还没有完全掌握Kotlin协程.

I still haven't fully grasped Kotlin coroutines yet.

基本上,我希望协程在执行之前等待所有先前的调用完成.以下代码似乎有效.但是它在做我认为正在做的事情吗?

Basically I want a coroutine to wait for any previous calls to finish before executing. The following code seems to work. But is it doing what I think it's doing?

private var saveJob: Job? = null

fun save() {
    saveJob = someScope.launch {
        saveJob?.join()
        withContext(Dispatchers.IO) {
            // suspending database operation
        }
    }
}

据我所知,代码正在执行我想要的操作.但是吗?

As far as I can tell, the code is doing what I want. But is it?

推荐答案

请记住,launch ed代码与它外部的代码是并发的.这意味着您编写的内容具有竞争条件:当您尝试对新作业进行join()时,外部代码可能已经将新作业分配给了saveJob,从而导致死锁.

Keep in mind that the launched code is concurrent to the code outside it. That means that what you wrote has a race condition: the outside code may have already assigned the new job to saveJob when you try to join() it, resulting in a deadlock.

我猜您想在后台触发save操作,该操作本身将提取所有数据以从其他位置保存.您可能不需要队列save的作业,只需确保在调用save()的位置保存了所有内容.如果您稍早调用了save并且尚未开始新的保存作业,则可以将这两个调用合并为一个save操作.

I guess what you want is to trigger a save operation in the background, and the operation itself will pull all the data to save from somewhere else. You probably don't want a queue of save jobs, just ensure that everything is saved at the point you call save(). If you called save a bit earlier and a new save job hasn't yet started, those two calls can be coalesced into a single save operation.

此外,您说您有一个挂起数据库操作.暂停代码不属于IO调度程序,只有在您必须同时执行许多 blocking 操作时,该代码才存在.

Furthermore, you say that you have a suspending database operation. Suspending code doesn't belong in the IO dispatcher, which is there only if you have to perform many blocking operations concurrently.

所有人都建议我建议使用演员:

All told I'd suggest using an actor:

val actor = someScope.actor<Unit>(capacity = CONFLATED) {
    // suspending database operation
}

fun save() = someScope.launch {
    actor.send(Unit)
}

这篇关于让协程等待先前的呼叫的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆