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()
都在做同样的事情吗?
更新:请参见Why does withContext await for the completion of child coroutines
上的讨论答案 0 :(得分:2)
这是两种作用域函数的行为完全相同的两种情况:
withContext(coroutineContext) { ... }
coroutineScope { ... }
都等待您在块中启动的所有协程完成。如果它们中的任何一个失败,则两者都会自动取消所有其他协程,并且整个块将引发异常,但不会自动取消您从中调用它们的协程。
但是,无论相同的行为如何,每个功能都有不同的用途并发出不同的意图。
coroutineScope
关于几个子协程的作用域生命周期。它用于将一个任务分解为多个并发子任务。您无法使用它来更改上下文,因此它从当前上下文继承了Dispatcher
。通常,如果需要,每个子协程将指定不同的Dispatcher
。
withContext
不用于启动子协程,它使当前协程暂时切换上下文,并应在其代码块完成后立即完成。它的主要用例是将很长的操作从事件循环线程(例如主GUI线程)转移到使用自己的线程池的Dispatcher
上。另一个用例是定义一个“关键部分”,在该部分中协程将不会对取消请求做出反应。