为什么withContext等待子协程的完成 [英] Why does withContext await for the completion of child coroutines

查看:163
本文介绍了为什么withContext等待子协程的完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

文档> 状态

使用给定的协程上下文调用指定的暂停块,暂停直到完成,然后返回结果.

Calls the specified suspending block with a given coroutine context, suspends until it completes, and returns the result.

但是,实际行为是它也在所有子协程上等待,并且不一定返回块的结果,而是在子协程中传播任何异常.

However, the actual behavior is that it awaits on all the child coroutines as well, and doesn't necessarily return the result of the block but instead propagates any exception in the child coroutine.

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.

I would expect the above to print result: 42 and then, possibly, print the uncaught exception from the child coroutine. Instead it waits for one second and then prints Error: launched coroutine broke.

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

The actual behavior, therefore, matches that of the coroutineScope builder. While it may be a useful behavior, I think it contradicts the documentation. Should the documentation be updated to something similar to coroutineScope?

该函数在给定的块及其所有子协程完成后立即返回.

This function returns as soon as the given block and all its children coroutines are completed.

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

Furthermore, does that mean that we can use coroutineScope and withContext(coroutineContext) interchangeably, the only difference being a bit less boilerplate?

推荐答案

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

withContext creates a new job. This means that all coroutines launched inside are children of this job. It only returns when the job is finished. Because of structured concurrency, it only finishes when all child coroutines are finished too.

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

When any of the child jobs fails, the parent job is canceled. This will also cancel all other child jobs. Since withContext returns a result, the exception is thrown.

文档CoroutineScope中的>在这方面很有帮助:

The documentation of CoroutineScope is helpful in this regards:

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

Every coroutine builder (like launch, async, etc) and every scoping function (like coroutineScope, withContext, etc) provides its own scope with its own Job instance into the inner block of code it runs. By convention, they all wait for all the coroutines inside their block to complete before completing themselves, thus enforcing the discipline of structured concurrency.

我认为withContext的文档也可以改进. JobCoroutineContext的文档非常有用,因为它们提供了更高层次的观点.

I think the documentation of withContext could be improved too. The documentation of Job and CoroutineContext are very helpful as they provide a more high-level point of view.

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

Furthermore, does that mean that we can use coroutineScope and withContext(coroutineContext) interchangeably, the only difference being a bit less boilerplate?

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

Yes, they should behave the same way. They are intended for different use cases though.

coroutineScope旨在为多个并行协程提供一个作用域,如果有任何失败,所有协程将被取消.

coroutineScope is meant to provide a scope for multiple parallel coroutines in which all will be canceled, if any fails.

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

withContext is designed to be used to switch the context (eg. the Dispatcher) for the given block of code.

此处我最近在kotlin论坛上提出了类似的问题.该线程包含更多类似的案例和进一步的见识.

Here is a similar question I recently asked on the kotlin discussion forums. The thread contains some more similar cases and further insight.

这篇关于为什么withContext等待子协程的完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆