Kotlin Coroutines:等待多个线程完成



因此,第一次查看coroutines,我想并行处理大量数据并等待它完成。我一直在环顾四周,看过奔跑,等待等等,但不确定如何使用它。

我到目前为止有

val jobs = mutableListOf<Job>()
jobs += GlobalScope.launch { processPages(urls, collection) }
jobs += GlobalScope.launch { processPages(urls, collection2) }
jobs += GlobalScope.launch { processPages(urls, collection3) }

我想知道/等待这些完成

,如果您使用结构化并发的概念,则无需手动跟踪您的工作。假设您的processPages函数执行某种阻止IO,则可以将代码封装到以下悬挂函数中,该功能将代码执行的IO调度程序中执行您的代码:

suspend fun processAllPages() = withContext(Dispatchers.IO) { 
    // withContext waits for all children coroutines 
    launch { processPages(urls, collection) }
    launch { processPages(urls, collection2) }
    launch { processPages(urls, collection3) }
}

现在,如果您的应用程序的最高功能还不是悬挂函数,那么您可以使用runBlocking调用processAllPages

runBlocking {
    processAllPages()
}

您可以使用async构建器函数并行处理大量数据:

class Presenter {
    private var job: Job = Job()
    private var scope = CoroutineScope(Dispatchers.Main + job) // creating the scope to run the coroutine. It consists of Dispatchers.Main (coroutine will run in the Main context) and job to handle the cancellation of the coroutine.
    fun runInParallel() {
        scope.launch { // launch a coroutine
            // runs in parallel
            val deferredList = listOf(
                    scope.asyncIO { processPages(urls, collection) },
                    scope.asyncIO { processPages(urls, collection2) },
                    scope.asyncIO { processPages(urls, collection3) }
            )
            deferredList.awaitAll() // wait for all data to be processed without blocking the UI thread
            // do some stuff after data has been processed, for example update UI
        }
    }
    private fun processPages(...) {...}
    fun cancel() {
        job.cancel() // invoke it to cancel the job when you don't need it to execute. For example when UI changed and you don't need to process data
    }
}

扩展功能asyncIO

fun <T> CoroutineScope.asyncIO(ioFun: () -> T) = async(Dispatchers.IO) { ioFun() } // CoroutineDispatcher - runs and schedules coroutines

GlobalScope.launch不建议使用,除非您希望Coroutine在整个应用程序寿命上运行而不过早取消。

编辑:如罗马·伊丽莎白(Roman Elizarov)所述,除非您要更新UI或在处理所有数据后立即进行其他操作,否则您可以尝试不使用awaitAll()功能。

可以使用以下方法。

fun myTask() {
    GlobalScope.launch {
        val task = listOf(
            async {
            },
            async {
            }
        )
        task.awaitAll()
    }
}

相关内容

  • 没有找到相关文章

最新更新