Dico
10/11/2019, 4:32 PMprivate val termination = CountDownLatch(1)
private val scope = dispatcher + Job().apply {
thread {
// use non-dameon thread to keep application alive until all tasks completed.
termination.await()
while (children.any { it.isActive }) Thread.sleep(50)
}
}
fun shutdown() {
termination.countDown()
}
streetsofboston
10/11/2019, 4:40 PMval scope : CoroutineScope = ...
fun main() = {
val job = scope.launch { ... do all my tasks within this coroutine ... }
runBlocking { job.join() }
}
Dico
10/11/2019, 4:41 PMjoin()
on a forever active parent Job no?streetsofboston
10/11/2019, 4:45 PMrunBlocking { job.join() }
instead of while (children....) { ... }
?
(the job
is the Job()
of your scope)Dico
10/11/2019, 4:45 PMJob()
of my scope is never cancelledstreetsofboston
10/11/2019, 4:46 PMDico
10/11/2019, 4:49 PMrunBlocking {
scope.coroutineContext[Job]!!.children.toList().joinAll()
}
streetsofboston
10/11/2019, 4:50 PMDico
10/11/2019, 4:50 PMjoin()
on the parent job causes the thread to hang indefinitelystreetsofboston
10/11/2019, 4:54 PMfun main() {
val parentJob = Job()
val scope = CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO> + parentJob)
println("Start")
val job = scope.launch {
launch { delay(1000) }
launch { delay(2000) }
launch { delay(2000) }
launch { delay(2000) }
launch { delay(2000) }
launch { delay(2000) }
launch { delay(2000) }
launch { delay(2000) }
launch { delay(2000) }
}
runBlocking { parentJob.children.toList().joinAll() }
println("Done")
}
(it also works when replacing parentJob
with job
inside the runBlocking { ... }
)parentJob
has only one child, job
has 9 children)Dico
10/11/2019, 4:59 PMstreetsofboston
10/11/2019, 5:04 PMgildor
10/12/2019, 5:10 AMDico
10/13/2019, 7:20 AMuli
10/14/2019, 3:14 AMDico
10/14/2019, 5:50 PMuli
10/14/2019, 6:01 PMDico
10/17/2019, 6:13 AMuli
10/17/2019, 6:43 AMDico
10/17/2019, 7:17 AMgildor
10/17/2019, 7:32 AMchannel to be closed when the parent job completes or gets cancelledSounds like you need Flow
Dico
10/17/2019, 11:55 AM