提问者:小点点

kotlin协程,协程Scope和withContext有什么区别


withContext
suspend fun <T> withContext(
    context: CoroutineContext, 
    block: suspend CoroutineScope.() -> T
): T (source)
Calls the specified suspending block with a given coroutine context, suspends until it completes, and returns the result.
suspend fun <R> coroutineScope(
    block: suspend CoroutineScope.() -> R
): R (source)
Creates a CoroutineScope and calls the specified suspend block with this scope. The provided scope inherits its coroutineContext from the outer scope, but overrides the context’s Job.

withContext采用CoroutineContext,在它的所有子项都完成后,两者似乎都是完成

在什么情况下,with Context协程范围应该比另一个优先?

例如:

suspend fun processAllPages() = withContext(Dispatchers.IO) { 
    // withContext waits for all children coroutines 
    launch { processPages(urls, collection) }
    launch { processPages(urls, collection2) }
    launch { processPages(urls, collection3) }
}

也可能是

suspend fun processAllPages() = coroutineScope { 
    // coroutineScope waits for all children coroutines 
    launch { processPages(urls, collection) }
    launch { processPages(urls, collection2) }
    launch { processPages(urls, collection3) }
}

两个process AllPages()都在做同样的事情吗?

更新:请参阅为什么with Context等待子协程完成的讨论


共1个答案

匿名用户

形式上,coroutineScopewith Context的一个特例,您在当前上下文中传递,避免了任何上下文切换。示意性地说,

coroutineScope ≡ withContext(this.coroutineContext)

由于切换上下文只是withContext的几个特性之一,这是一个合法的用例。withContext等待你在块内启动的所有协程完成。如果其中任何一个失败,它将自动取消所有其他协程,整个块将抛出异常,但不会自动取消你调用它的协程。

每当您需要这些功能而无需切换上下文时,您应该始终更喜欢coroutineScope,因为它更清楚地表明您的意图。

coroutineScope是关于几个子协程的作用域生命周期。它用于将任务分解为几个并发子任务。您无法使用它更改上下文,因此它从当前上下文继承Dispatcher。通常,如果需要,每个子协程都会指定不同的Dispatcher

withContext通常不用于启动子协程,而是临时切换当前协程的上下文。它应该在其代码块完成后立即完成(从版本1.3.2开始,这实际上仍然在其留档中说明)。它的主要用例是将长操作从事件循环线程(例如GUI主线程)卸载到使用自己线程池的Dispatcher。另一个用例是定义一个“临界区”,其中协程不会对取消请求做出反应。