withContext
国的文档
使用给定的协程上下文调用指定的暂停块,直到完成为止暂停并返回结果。
但是,实际行为是它也在所有子协程上等待,并且不一定返回块的结果,而是在子协程中传播任何异常。
suspend fun main() {
try {
val result = withContext(coroutineContext) {
launch {
delay(1000L)
throw Exception("launched coroutine broke")
}
println("done launching")
42
}
println ("result: $result")
} catch (e: Exception) {
println("Error: ${e.message}")
}
}
我希望上面的命令打印result: 42
,然后可能从子协程打印未捕获的异常。而是等待一秒钟,然后打印Error: launched coroutine broke
。
因此,实际行为与coroutineScope
构建器的行为匹配。虽然这可能是有用的行为,但我认为它与文档相矛盾。应该将文档更新为类似于coroutineScope
的内容吗?
该函数在给定的块及其所有子协程完成后立即返回。
此外,这是否意味着我们可以互换使用coroutineScope
和withContext(coroutineContext)
,唯一的区别是样板要少一些?
答案 0 :(得分:2)
withContext
创建一个新工作。这意味着内部发布的所有协程都是该工作的孩子。仅在作业完成时返回。由于结构化并发,它仅在所有子协程也都完成时才能完成。
任何子作业失败时,父作业将被取消。这也将取消所有其他子项工作。由于withContext
返回结果,因此引发了异常。
CoroutineScope
中的documentation在这方面很有帮助:
每个协程生成器(如启动,异步等)和每个作用域函数(如coroutineScope,withContext等)在其运行的内部代码块中都提供具有自己的Job实例的范围。按照惯例,它们所有人都在等待自己的块中的所有协程完成后再完成自己,从而加强了结构化并发的纪律。
我认为withContext
的文档也可以改进。 Job
和CoroutineContext
的文档非常有用,因为它们提供了更高层次的观点。
此外,这是否意味着我们可以互换使用coroutineScope和withContext(coroutineContext),唯一的区别是样板要少一些?
是的,它们的行为应相同。它们旨在用于不同的用例。
coroutineScope
旨在为多个并行协程提供一个范围,如果有任何失败,所有的协程都将被取消。
withContext
旨在用于切换给定代码块的上下文(例如Dispatcher)。
Here是我最近在kotlin论坛上提出的类似问题。该线程包含更多类似的案例和进一步的见识。