在Kotlin中以同步方式运行异步任务 [英] Running asynchronous tasks in synchronous way in Kotlin

查看:85
本文介绍了在Kotlin中以同步方式运行异步任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试运行Firebase Firestore的批处理"作业.由于批处理作业是异步的,并且每个批处理仅处理500个文档,因此我创建了一系列要以同步方式运行的批处理作业,以便我确切地知道上一个批处理何时完成,然后继续进行下一个批处理.操作.

I am trying to run a 'batch' job of Firebase Firestore. Since batch job is asynchronous, and every batch processes only 500 documents, I have created an array of batch jobs that I want to run in a synchronous way, so that I know exactly when the last batch is done, and then proceed with the next operation.

但是,当我在Kotlin进行阅读时,遇到了诸如runBlocking,Coroutine,Dispatcher,async,await,Context,Suspend,launch,join,Scope,Deferred,Continuation,CommonPool之类的术语

However, to do this in Kotlin, when I read up, I have come across a sleuth of jargons like runBlocking, Coroutine, Dispatcher, async, await, Context, Suspend, launch, join, Scope, Deferred, Continuation, CommonPool

此外,许多帖子都说,在最新版的Kotlin中,情况已经改变.Kotlin 文档讨论了runBlocking,但

Furthermore, many of the posts say that in the latest version of Kotlin things have changed. Kotlin documentation talks about runBlocking, but this post says runBlocking is bad thing.

经过一番尝试和错误后,我得到了它进行编译

After some trial and error I got this to get compiled

suspend fun doTheThing() {

   for ( b in batchArray) {
      coroutineScope {
      val job = async { b.commit() }
      job.await()
  }}
}

但是,现在我收到错误消息,仅应从协程或其他暂停函数调用暂停函数'doTheThing'"我现在很困惑.我只想按顺序执行这些调用,或者等到所有这些完成为止.不确定完成此操作的正确语法是什么,我弄错了什么概念.

However, now I am getting the error saying "Suspend function 'doTheThing' should be called only from a coroutine or another suspend function" I am just confused at the moment. I just want to do those calls in sequence, or wait till all of those are done. Not sure what is the right syntax to get this done, and what concepts am I getting wrong.

更新:以下代码段似乎有效:

Update: Following code snippet seems to be working:

for ( b in batchArray) {
    runBlocking {b.commit()}
}

这样做是一种好习惯吗?

Is it a good practice to do it like this?

推荐答案

请参阅下面的解决方案,在该解决方案中,您要从中开始的主要功能开始批处理作业操作,您需要定义所有500个文档将在哪个线程上处理.因此,您可以使用IO分配器初始化Coroutine范围,并在其中调用主要处理方法.

Please see the solution below where your main function from which you are starting you batch job operation you need to define on which thread all 500 documents will process. So you initialise a Coroutine scope with IO dispatcher.And call you main processing method inside it.

科特林有三名调度员

  • IO 用于网络和磁盘IO的相关工作.
  • 默认用于复杂的操作,例如遍历列表或数学运算.
  • 主要,用于将结果保存到UI或与UI相关的操作中.
  • IO for network and disk IO related work.
  • Default used for complex operations like list traversal or mathematical operations.
  • Main for positing results to UI or UI related operations.

现在,由于您希望所有500个文档并行处理,因此您可以在该后台线程内创建一个同步块.除非所有异步块(.commit)操作没有完成,否则该同步块将不会完成.

Now, since you want all 500 documents to process in parallel so you create a synchronous block inside that background thread. This synchronous block will not be completed unless all the asynchronous blocks (.commit) operation is not completed.

我想您可以通过这种方式实现所需的行为.请在下面查看相同的代码:

I guess in this way you can achieve the behavior you want. Please see the code for same below:

fun initialFunction() {

   //inside this function start the Coroutine using launch
   //using Dispatcher.IO will perform execution of coroutine in background/IO
   CoroutineScope(Dispatchers.IO).launch {

      //call your method which will process batch job asynchronously
      doTheThing()

   }
}

suspend fun doTheThing() {
  //now start your blocking call, this execute following block 
  //synchronously 
  runBlocking {
     for ( b in batchArray) {

     //commit will run synchronously and following nested coroutine
     //will wait for job to get completed 
     launch {
        val job = async { b.commit() }
        job.await()
     }

    }
  }
}

这篇关于在Kotlin中以同步方式运行异步任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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