为什么withContext等待子协程的完成

Mar*_*nik 4 kotlin kotlin-coroutines withcontext

的文档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}")
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望可以打印出上述内容result: 42,然后再打印子协程中未捕获的异常。而是等待一秒钟,然后打印Error: launched coroutine broke

因此,实际行为与coroutineScope构建者的行为相匹配。虽然这可能是有用的行为,但我认为它与文档相矛盾。应该将文档更新为类似内容coroutineScope吗?

给定的块及其所有子协程完成后,此函数将立即返回。

此外,这是否意味着,我们可以使用coroutineScopewithContext(coroutineContext)互换,是少了几分样板唯一的区别?

Flo*_*ann 5

withContext创建新工作。这意味着内部发布的所有协程都是该工作的孩子。仅在作业完成时返回。由于结构化并发,它仅在所有子协程也都完成时才完成。

当任何子作业失败时,父作业将被取消。这也将取消所有其他子项工作。由于withContext返回结果,因此将引发异常。

文档CoroutineScope是在这方面有所帮助:

每个协程构建器(如启动,异步等)和每个作用域函数(如coroutineScope,withContext等)在运行的内部代码块中提供其自己的范围以及自己的Job实例。按照惯例,它们都在等待自己的块中的所有协程完成之前才完成自身,从而加强了结构化并发的纪律。

我认为的文档withContext也可以改进。的文件JobCoroutineContext非常有益,因为它们提供的视图中的更高层的点。

此外,这是否意味着我们可以互换使用coroutineScope和withContext(coroutineContext),唯一的区别就是样板要少一些?

是的,它们的行为应相同。它们旨在用于不同的用例。

coroutineScope 旨在为多个并行协程提供一个作用域,如果有任何失败,则将全部取消。

withContext 设计用于切换给定代码块的上下文(例如Dispatcher)。

是我最近在kotlin论坛上提出的类似问题。该线程包含更多类似案例和更多见解。