コルーチンを使用して複数のジョブを並行して実行したい。これは私が思いついたコードです。
2つのクエリがあります:
呼び出し元のスレッドで完了コールバックが発生するようにするにはどうすればよいですか?
コードは、通常のスレッドで使用していたコールバックパターンのようになりました。コルーチンの読みやすさの利点を実現するために、デザインの変更を提案してください。
class ParallelExecutor {
suspend fun <OUTPUT> execute(
jobs: List<suspend () -> OUTPUT>,
onTimeout: (jobIndex: Int) -> OUTPUT,
onFailure: (jobIndex: Int, exception: Throwable) -> OUTPUT,
onCompletion: suspend (jobIndex: Int, result: OUTPUT) -> Unit,
timeout: Long,
onFullCompletion: suspend () -> Unit = {},
invokeDispatcher: CoroutineDispatcher = Dispatchers.Default
) {
withContext(invokeDispatcher) {
var counter = 0
val listenJobs = mutableListOf<Deferred<OUTPUT>>()
jobs.forEachIndexed { index, job ->
val listenJob = async {
try {
job()
} catch (e: Exception) {
onFailure(index, e)
}
}
listenJobs.add(listenJob)
}
listenJobs.forEachIndexed { index, job ->
launch {
val output = try {
withTimeout(timeout) {
job.await()
}
} catch (e: TimeoutCancellationException) {
onTimeout(index)
}
onCompletion(index, output)
if (++counter == listenJobs.size) {
onFullCompletion()
}
}
}
}
}
}
コードをかなり単純化できるように思えます。最初にすべてのasync
ジョブを起動し、次にそれらを待機するためにさらにジョブを起動する2段階のイディオムは必要ありません。launch
同じブロック内でジョブとコールバックに委任することができます。そうすれば、コールバックは呼び出し元のディスパッチャーで自然に呼び出され、変更されたコンテキスト内でジョブ自体のみを呼び出すことができますinvokeDispatcher
。
onFullCompletion
呼び出しの下の呼び出し側に属するコードの一部のように見えexecute
ます。以来execute
、例外をスローしません、あなたはいずれかを必要としないtry-finally
、それを取得します。
suspend fun <OUTPUT> execute(
jobs: List<suspend () -> OUTPUT>,
onTimeout: (jobIndex: Int) -> OUTPUT,
onFailure: (jobIndex: Int, exception: Throwable) -> OUTPUT,
onCompletion: suspend (jobIndex: Int, result: OUTPUT) -> Unit,
timeout: Long,
invokeDispatcher: CoroutineDispatcher = Dispatchers.Default
) {
coroutineScope {
jobs.mapIndexed { index, job ->
launch {
val output = try {
withTimeout(timeout) {
withContext(invokeDispatcher) {
job()
}
}
} catch (e: TimeoutCancellationException) {
onTimeout(index)
} catch (e: Exception) {
onFailure(index, e)
}
onCompletion(index, output)
}
}
}
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加