何时使用 coroutineScope 与 supervisorScope?
When to use coroutineScope vs supervisorScope?
谁能解释一下这两者到底有什么区别?
你什么时候用一个代替另一个?
提前致谢。
我认为Roman Elizarov explain it quite in details,但简而言之:
协程创建以下类型的层次结构:
- 父协程
- 子协程 1
- 子协程 2
- ...
- 子协程 N
假设“Coroutine i”失败。你希望它的父级发生什么?
如果您希望其父级也失败,请使用 coroutineScope
。这就是结构化并发的意义所在。
但是如果你不希望它失败,例如 child 是某种可以再次启动的后台任务,那么使用 supervisorScope
。
解释差异的最好方法是解释 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())
}
compute()
从网络上抓取两个东西,组合成一个字符串描述。在这种情况下,第一次获取需要很长时间,但最终会成功;第二个在 100 毫秒后几乎立即失败。
您希望上述代码有什么行为?
要不要color.await()
一分钟,才发现对方网络调用早就失败了?
或者您可能希望 compute()
函数在 100 毫秒后意识到其网络调用之一失败并立即自行失败?
supervisorScope
你得到 1.,coroutineScope
你得到 2.
2. 的行为意味着,即使 async
本身不抛出异常(它只是完成了你从它那里得到的 Deferred
),失败会立即取消它的协程,这取消了 parent,然后取消了所有其他 children。
当您没有意识到时,这种行为可能会很奇怪。如果你去捕获来自 await()
的异常,你会认为你已经从中恢复过来,但你没有。整个协程作用域仍在取消中。在某些情况下,您不想要它是有正当理由的:那就是您将使用 supervisorScope
.
主要区别在于协程作用域将在其任何 children 失败时取消。如果我们想在一个任务失败时继续执行其他任务,我们可以使用 supervisorScope。当其中一个失败时,supervisorScope 不会取消其他 children。
这里有一个有用的link,可以详细理解协程:
https://blog.mindorks.com/mastering-kotlin-coroutines-in-android-step-by-step-guide
谁能解释一下这两者到底有什么区别?
你什么时候用一个代替另一个?
提前致谢。
我认为Roman Elizarov explain it quite in details,但简而言之:
协程创建以下类型的层次结构:
- 父协程
- 子协程 1
- 子协程 2
- ...
- 子协程 N
假设“Coroutine i”失败。你希望它的父级发生什么?
如果您希望其父级也失败,请使用 coroutineScope
。这就是结构化并发的意义所在。
但是如果你不希望它失败,例如 child 是某种可以再次启动的后台任务,那么使用 supervisorScope
。
解释差异的最好方法是解释 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())
}
compute()
从网络上抓取两个东西,组合成一个字符串描述。在这种情况下,第一次获取需要很长时间,但最终会成功;第二个在 100 毫秒后几乎立即失败。
您希望上述代码有什么行为?
要不要
color.await()
一分钟,才发现对方网络调用早就失败了?或者您可能希望
compute()
函数在 100 毫秒后意识到其网络调用之一失败并立即自行失败?
supervisorScope
你得到 1.,coroutineScope
你得到 2.
2. 的行为意味着,即使 async
本身不抛出异常(它只是完成了你从它那里得到的 Deferred
),失败会立即取消它的协程,这取消了 parent,然后取消了所有其他 children。
当您没有意识到时,这种行为可能会很奇怪。如果你去捕获来自 await()
的异常,你会认为你已经从中恢复过来,但你没有。整个协程作用域仍在取消中。在某些情况下,您不想要它是有正当理由的:那就是您将使用 supervisorScope
.
主要区别在于协程作用域将在其任何 children 失败时取消。如果我们想在一个任务失败时继续执行其他任务,我们可以使用 supervisorScope。当其中一个失败时,supervisorScope 不会取消其他 children。
这里有一个有用的link,可以详细理解协程:
https://blog.mindorks.com/mastering-kotlin-coroutines-in-android-step-by-step-guide