我正在尝试处理数据对象树。每个树叶都应该通过使用协程的函数进行处理。整个过程应使用固定大小的线程池完成。
所以我想出了这个:
val node = an instance of WorkspaceEntry (tree structure)
val localDispatcher = newFixedThreadPoolContext(16)
fun main() {
val job = SupervisorJob()
val scope = CoroutineScope(localDispatcher + job)
handleEntry(node, scope)
runBlocking {
job.join()
}
}
handleEntry 方法在主管中为每片树叶递归启动一个子作业。
主管的子作业全部成功完成,但联接永远不会返回。我理解错了吗?
编辑:句柄输入功能
private fun handleEntry(workspaceEntry: WorkspaceEntry, scope: CoroutineScope) {
if (workspaceEntry is FileEntry) {
scope.launch {
FileTypeRegistry.processFile(workspaceEntry.fileBlob)
}
} else {
workspaceEntry.children.forEach { child -> handleEntry(child, scope) }
}
}
似乎用于创建CoroutineContext
的Job
(在您的情况下SupervisorJob
)不是用于等待子协程完成,因此您不能使用 job.join()
.我想该Job
的主要目的是取消子协程。将runBlocking
块更改为以下内容将起作用:
runBlocking {
job.children.forEach {
it.join()
}
}
您混合了两个角色:
- 在协程作用域中找到的主作业,它永远不会自行完成,用于控制其他所有内容的生命周期
- 对应于工作单元的作业,可能分解为多个子作业
您需要两者,如下所示:
val masterJob = SupervisorJob()
val scope = CoroutineScope(localDispatcher + masterJob)
val unitOfWork = scope.launch { handleEntry(node, scope) }
runBlocking { unitOfWork.join() }
上面的代码并没有真正激发主作业的存在,因为你只从它开始一个子作业,但它在更广泛的图片中可能是有意义的,你有一些上下文,你可以从中启动许多作业,并希望能够编写
masterJob.cancel()
在完成之前取消所有内容。