_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
のいくつかの機能の1つにすぎないため、これは正当な使用例です。 withContext
は、ブロック内で開始したすべてのコルーチンが完了するまで待機します。それらのいずれかが失敗すると、他のすべてのコルーチンが自動的にキャンセルされ、ブロック全体で例外がスローされますが、呼び出し元のコルーチンは自動的にキャンセルされません。
コンテキストを切り替えることなくこれらの機能が必要な場合は、意図をより明確に伝えるため、常にcoroutineScope
を優先する必要があります。
coroutineScope
は、いくつかのサブコルーチンのスコープ付きライフサイクルに関するものです。タスクをいくつかの同時サブタスクに分解するために使用されます。コンテキストを変更することはできないため、現在のコンテキストからDispatcher
を継承します。通常、各サブコルーチンは、必要に応じて異なるDispatcher
を指定します。
withContext
は通常、サブコルーチンの開始には使用されませんが、現在のコルーチンのコンテキストを一時的に切り替えるために使用されます。コードブロックが完了するとすぐに完了します(バージョン1.3.2以降、これは実際にはまだドキュメントに記載されています)。その主な使用例は、長い操作をイベントループスレッド(メインGUIスレッドなど)から、独自のスレッドプールを使用するDispatcher
にオフロードすることです。別の使用例は、コルーチンがキャンセル要求に反応しない「クリティカルセクション」を定義することです。