Reputation: 11387
Given this piece of code
fun main() {
val job = Job()
val scope = GlobalScope + job
scope.launch {
println("working!")
delay(1000L)is ms)
println("done!")
// how do i finish the job originally associated with this scope?
}
runBlocking {
job.join()
println("job done")
}
}
I have a custom coroutine scope for my application, and i'm associating a job with this scope like that, reason being i want all the new coroutines that are created from this scope to be the children of this job, if i cancel it i want everything in it to be cancelled.
But main job itself is never completing. How do i complete the main job when the task is done? or failed...
Upvotes: 0
Views: 2406
Reputation: 26
Let's simplify your code to something like this:
val job = Job()
runBlocking {
job.join()
}
If you run this code you will see that it also never completes. That is because job.join()
suspends until the given job reaches a terminal state which is either completed
or canceled
(see docs).
When you create a job using some coroutine builder (like .launch {...}
) you do not need to complete it by yourself. But since you have created it using a factory method Job()
it is now your responsibility to complete it.
You can also find more detailed explanation here.
Upvotes: 1
Reputation: 6258
The main job works only as the parent job and will never complete. But you could wait for all children to complete:
runBlocking {
job.children.forEach { it.join() }
println("job done")
}
Alternatively you should go with Eugene's solution and invoke the join
method of the Job
you just started, instead of the main job.
Upvotes: 3
Reputation: 4992
There are several functions to wait for a Job()
object to complete and to cancel it. You may pick one from the list
job.cancel()
job.join()
job.cancelAndJoin()
Only the first function is not a suspend
function, so you may call it from every other function, not necessarily a suspend
functions
There is a better way - the launch{..}
function already returns Job
object from the call. You may simplify the code to say
val job = GlobalScope.launch { .. }
that Job
object will automatically complete when launch block is over or failed with an exception
Upvotes: 1