问题
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.
the withContext takes CoroutineContext, and both seems to be complete
after all its children are complete.
In what case the withContext
or the coroutineScope
should be preferred than the other?
for example:
suspend fun processAllPages() = withContext(Dispatchers.IO) {
// withContext waits for all children coroutines
launch { processPages(urls, collection) }
launch { processPages(urls, collection2) }
launch { processPages(urls, collection3) }
}
could also be
suspend fun processAllPages() = coroutineScope {
// coroutineScope waits for all children coroutines
launch { processPages(urls, collection) }
launch { processPages(urls, collection2) }
launch { processPages(urls, collection3) }
}
are the both processAllPages()
doing the same?
update: see discuss at Why does withContext await for the completion of child coroutines
回答1:
Formally, coroutineScope
is a special case of withContext
where you pass in the current context, avoiding any context switching. Schematically speaking,
coroutineScope ≡ withContext(this.coroutineContext)
Since switching contexts is just one of several features of withContext
, this is a legitimate use case. withContext
waits for all the coroutines you start within the block to complete. If any of them fail, it will automatically cancel all the other coroutines and the whole block will throw an exception, but won't automatically cancel the coroutine you're calling it from.
Whenever you need these features without needing to switch contexts, you should always prefer coroutineScope
because it signals your intent much more clearly.
coroutineScope
is about the scoped lifecycle of several sub-coroutines. It's used to decompose a task into several concurrent subtasks. You can't change the context with it, so it inherits the Dispatcher
from the current context. Typically each sub-coroutine will specify a different Dispatcher
if needed.
withContext
is not typically used to start sub-coroutines, but to temporarily switch the context for the current coroutine. It should complete as soon as its code block completes (as of version 1.3.2, this is actually still stated in its documentation). Its primary use case is offloading a long operation from the event loop thread (such as the main GUI thread) to a Dispatcher
that uses its own thread pool. Another use case is defining a "critical section" within which the coroutine won't react to cancellation requests.
来源:https://stackoverflow.com/questions/56858624/kotlin-coroutines-what-is-the-difference-between-coroutinescope-and-withcontext