何时使用coroutineScope与SupervisorScope?

Arc*_*nes 5 kotlin kotlin-coroutines

有人可以解释这两者之间到底有什么区别吗?

什么时候使用另一种?

提前致谢。

Ehs*_*adi 18

coroutineScope->每当任何子级失败时,作用域及其所有子级都会失败

supervisorScope->只要任何子级失败,作用域及其所有子级不会失败


Ale*_*hin 13

我认为Roman Elizarov 解释得很详细,但要简短:

你有这种层次结构:

  • 父协程
    • 子协程 1
    • 子协程 2
    • ...
    • 子协程 N

假设“Coroutine i”失败。你想和它的父母发生什么?

如果您希望其父级也失败,请使用coroutineScope. 这就是结构化并发的全部意义所在。

但是,如果您不希望它失败,例如 child 是某种可以再次启动的后台任务,则使用supervisorScope.


Mar*_*nik 12

解释差异的最好方法是解释差异的机制coroutineScope。考虑以下代码:

suspend fun main() = println(compute())

suspend fun compute(): String = coroutineScope {
    val color = async { delay(60_000); "purple" }
    val height = async<Double> { delay(100); throw HttpException() }
    "A %s box %.1f inches tall".format(color.await(), height.await())
}
Run Code Online (Sandbox Code Playgroud)

compute()从网络中获取两件事,并将它们组合为字符串描述。在这种情况下,第一次获取会花费很长时间,但最终会成功;第二个在100毫秒后几乎立即失败。

您想要上述代码的什么行为?

  1. 您是否想color.await()一会儿才意识到另一个网络呼叫长期失败?

  2. 还是您希望compute()函数在100毫秒后意识到其网络调用之一失败并立即失败?

随着supervisorScope你得到1,随着coroutineScope你得到2。

2.的行为意味着,即使async本身没有引发异常(它只是完成Deferred了从异常中得到的结果),失败也立即取消了它的协程,从而取消了父级,然后取消了所有其他子级。

当您不知道此行为时,可能会很奇怪。如果您从中捕获了异常await(),您会认为您已经从中恢复了,但还没有。整个协程范围仍然被取消。在某些情况下,您有合理的理由不想要它:那就是您要使用的时间supervisorScope


Lio*_*ior 6

正如@N1hk 提到的,如果你使用async调用顺序await很重要。如果您依赖于两个asynch..await块的结果,那么尽早取消是有意义的,所以这不是一个理想的例子supervisorScope

launch使用and时差异更加明显join

fun main() = runBlocking {
    supervisorScope {
        val task1 = launch {
            println("Task 1 started")
            delay(100)
            if (true) throw Exception("Oops!")
            println("Task 1 completed!")
        }
        val task2 = launch {
            println("Task 2 started")
            delay(1000)
            println("Task 2 completed!")
        }

        listOf(task1, task2).joinAll()
        println("Finished waiting for both tasks")
    }

    print("Done!")
}
Run Code Online (Sandbox Code Playgroud)

使用 时supervisorScope,输出将是:

Task 1 started
Task 2 started
Exception in thread "main" java.lang.Exception: Oops!
...
Task 2 completed!
Finished waiting for both tasks
Done!
Run Code Online (Sandbox Code Playgroud)

输出coroutineScope将是:

Task 1 started
Task 2 started
Run Code Online (Sandbox Code Playgroud)


Muh*_*han 5

CoroutineScope -> 每当它的任何子进程失败时就取消。

\n

SupervisorScope -> 如果我们想要继续执行其他任务,即使其中一项任务失败,我们也可以使用supervisorScope。当其他子级之一失败时,supervisorScope 不会取消\xe2\x80\x99。

\n

以下是详细了解协程的有用链接:

\n

https://blog.mindorks.com/mastering-kotlin-coroutines-in-android-step-by-step-guide

\n