kotlin协程,coroutineScope和withContext有什么区别
kotlin coroutines, what is the difference between coroutineScope and 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,并且在其所有子项完成后,两者似乎都是 complete
。
在什么情况下 withContext
或 coroutineScope
应该优先于另一个?
例如:
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) }
}
这两个 processAllPages()
是一样的吗?
更新:参见
的讨论
形式上,coroutineScope
是 withContext
的特例,您在其中传递当前上下文,避免任何上下文切换。概略地说,
coroutineScope ≡ withContext(this.coroutineContext)
由于切换上下文只是 withContext
的几个功能之一,这是一个合法的用例。 withContext
等待您在块中启动的所有协程完成。如果其中任何一个失败,它将自动取消所有其他协程并且整个块将抛出异常,但不会自动取消您从中调用它的协程。
每当您需要这些功能而不需要切换上下文时,您应该始终选择 coroutineScope
,因为它更清楚地表明您的意图。
coroutineScope
是关于几个 sub-coroutines 的作用域生命周期。它用于将一个任务分解为多个并发的子任务。您不能用它更改上下文,因此它从当前上下文继承了 Dispatcher
。如果需要,通常每个 sub-coroutine 会指定不同的 Dispatcher
。
withContext
一般不用于启动sub-coroutines,而是临时切换当前协程的上下文。它应该在其代码块完成后立即完成(从 1.3.2 版开始,这实际上仍在其文档中说明)。它的主要用例是将事件循环线程(例如主 GUI 线程)中的长操作卸载到使用自己的线程池的 Dispatcher
。另一个用例是定义一个 "critical section",其中协程不会对取消请求做出反应。
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,并且在其所有子项完成后,两者似乎都是 complete
。
在什么情况下 withContext
或 coroutineScope
应该优先于另一个?
例如:
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) }
}
这两个 processAllPages()
是一样的吗?
更新:参见
形式上,coroutineScope
是 withContext
的特例,您在其中传递当前上下文,避免任何上下文切换。概略地说,
coroutineScope ≡ withContext(this.coroutineContext)
由于切换上下文只是 withContext
的几个功能之一,这是一个合法的用例。 withContext
等待您在块中启动的所有协程完成。如果其中任何一个失败,它将自动取消所有其他协程并且整个块将抛出异常,但不会自动取消您从中调用它的协程。
每当您需要这些功能而不需要切换上下文时,您应该始终选择 coroutineScope
,因为它更清楚地表明您的意图。
coroutineScope
是关于几个 sub-coroutines 的作用域生命周期。它用于将一个任务分解为多个并发的子任务。您不能用它更改上下文,因此它从当前上下文继承了 Dispatcher
。如果需要,通常每个 sub-coroutine 会指定不同的 Dispatcher
。
withContext
一般不用于启动sub-coroutines,而是临时切换当前协程的上下文。它应该在其代码块完成后立即完成(从 1.3.2 版开始,这实际上仍在其文档中说明)。它的主要用例是将事件循环线程(例如主 GUI 线程)中的长操作卸载到使用自己的线程池的 Dispatcher
。另一个用例是定义一个 "critical section",其中协程不会对取消请求做出反应。