Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asynchronous 用kotlin协程并行分解独立异步任务_Asynchronous_Kotlin_Coroutine_Kotlin Coroutines - Fatal编程技术网

Asynchronous 用kotlin协程并行分解独立异步任务

Asynchronous 用kotlin协程并行分解独立异步任务,asynchronous,kotlin,coroutine,kotlin-coroutines,Asynchronous,Kotlin,Coroutine,Kotlin Coroutines,我试图并行运行多个任务,但这些任务是独立的,因此如果其中一个子协同程序失败,我不希望它的兄弟姐妹或父节点也失败。在下面的代码中,我使用了coroutineScope创建了一个新的作用域,在这个作用域中,这些任务运行并启动了5个异步任务,每个任务发送其id和它应该等待的延迟时间。第二个协同程序抛出一个异常。在本例中,代码执行我希望它执行的操作,它计算成功完成的作业和失败的作业的总和,返回0 然而,我读到kotlinx库中也有supervisorScope,这应该是首选,而不是coroutineSc

我试图并行运行多个任务,但这些任务是独立的,因此如果其中一个子协同程序失败,我不希望它的兄弟姐妹或父节点也失败。在下面的代码中,我使用了coroutineScope创建了一个新的作用域,在这个作用域中,这些任务运行并启动了5个异步任务,每个任务发送其id和它应该等待的延迟时间。第二个协同程序抛出一个异常。在本例中,代码执行我希望它执行的操作,它计算成功完成的作业和失败的作业的总和,返回0

然而,我读到kotlinx库中也有supervisorScope,这应该是首选,而不是coroutineScope(如果未处理异常,则取消父级/同级),因为任务不依赖于其他任务。我不知道为什么我应该改用supervisorScope,因为我用coroutineScope得到了我想要的结果

Q1:如果我要切换到supervisorScope,我的异步块是否会发生变化

Q2:是否接受捕获异步块内的任何异常,并且不让任何内容传播到其父块?我知道您也可以在.await()阶段捕获异常,但这是应该做的吗

runBlocking {
    coroutineScope {
            val job1 = async<Int> {
                try {
                    request(1, 1000)
                } catch (e: Exception) {
                    println("Job 1 failed with $e")
                    0
                }
            }

            val job2 = async<Int> {
                try {
                    request(2, 2000)
                    throw Exception("cancelling Job 2")
                } catch (e: Exception) {
                    println("Job 2 failed: $e")
                    0
                }
            }

            val job3 = async {
                try {
                    request(3, 3000)
                } catch (e: Exception) {
                    println("Job 3 failed with $e")
                    0
                }
            }

            val job4 = async {
                try {
                    request(4, 4000)
                } catch (e: Exception) {
                    println("Job 4 failed with $e")
                    0
                }
            }

            val job5 = async {
                try {
                    request(5, 5000)
                } catch (e: Exception) {
                    println("Job 5 failed with $e")
                    0
                }
            }

            val result = job1.await() + job2.await() + job3.await() + job4.await() + job5.await()
            println(result.toString())
        }

        println("Finished")
}


所有协同程序运行到完成的原因是,您在作业2本身中捕获了作业2引发的异常,因此它不会向上传播到作业的层次结构中,因此不会发生任何事情

但是,如果删除job2中的
catch
子句,作业[1-5]将始终被取消,这与使用
coroutineScope
supervisorScope
无关

这是因为
job2.await()
将引发异常。由于这发生在作业[1-5]的父作业内(即在顶部的
协同工作范围内
/
主管范围
),并且由于失败/取消的父作业总是取消子作业,因此作业[1-5]也将被取消

A1:不要使用
coroutineScope
supervisorScope
,删除
coroutineScope
,并将内容直接放在
运行阻塞


A2:当然可以在
async{}
中捕获异常,以确保它不会在
中发生。wait()
如果它适合您的用例。

好的,这是有意义的。那么应该采取什么样的方法呢?无论我使用
coroutineScope
supervisorScope
还是有更惯用的方法来处理这个问题,我都不明白在这种情况下为什么需要
coroutineScope
。继续做你要做的事情,即捕获失败子作业中的异常并使它们返回0,然后像你已经做的那样求和。只需删除当前的
coroutineScope
,并将所有内容直接移动到
runBlocking
下,就完成了。(当然,您可能想添加一些帮助函数以减少代码重复。当然,您也不应该在实际代码中使用
runBlocking
,但我怀疑您不会)。是的,这只是我提出的一个示例代码,但想法类似,我只是在一个循环中创建异步协程,因此我围绕它们创建了一个协程作用域。是的,我的代码中没有使用runBlocking是的,这里有一个输入错误
suspend fun request(id: Int, time: Long): Int {
    println("Job $id started")
    delay(time)
    println("Job $id finished")
    return id
}