首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >coroutineScope和withContext的区别是什么?

coroutineScope和withContext的区别是什么?
EN

Stack Overflow用户
提问于 2019-07-02 19:01:08
回答 1查看 8.8K关注 0票数 36
代码语言:javascript
复制
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.
代码语言:javascript
复制
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,在所有子级完成之后,两者似乎都是complete

在何种情况下,应该优先使用withContextcoroutineScope

例如:

代码语言:javascript
复制
suspend fun processAllPages() = withContext(Dispatchers.IO) { 
    // withContext waits for all children coroutines 
    launch { processPages(urls, collection) }
    launch { processPages(urls, collection2) }
    launch { processPages(urls, collection3) }
}

也可能是

代码语言:javascript
复制
suspend fun processAllPages() = coroutineScope { 
    // coroutineScope waits for all children coroutines 
    launch { processPages(urls, collection) }
    launch { processPages(urls, collection2) }
    launch { processPages(urls, collection3) }
}

这两个processAllPages()做的是一样的吗?

更新:参见在Why does withContext await for the completion of child coroutines讨论

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-03 09:08:09

在形式上,coroutineScopewithContext的一个特例,您可以在其中传递当前上下文,从而避免任何上下文切换。从原理上讲,

代码语言:javascript
复制
coroutineScope ≡ withContext(this.coroutineContext)

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

当您需要这些特性而不需要切换上下文时,您应该总是更喜欢coroutineScope,因为它更清楚地表明了您的意图。

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

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

票数 57
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56858624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档