I haven’t been able to reproduce this yet in an isolated example, however I’m seeing intermittent errors in my app that could be explained if, in the following example, “JOB 2” were printed after “EXIT SCOPE”:
suspend fun main() {
withContext(Dispatchers.Default) {
launch job1@{
this@withContext.launch { println("JOB 2") }
}
}
println("EXIT SCOPE")
}
I expect withContext()
to postpone “EXIT SCOPE” until at least job 1 is complete, by which time I expect job 2 will have been added to the scope, further postponing “EXIT SCOPE” until “JOB 2” is complete. Is this guaranteed, however?
In the right multithreaded environment, is it possible for withContext()
to end before job 2 is complete?
If this isn’t guaranteed I can instead arrange to call this@job1.launch { println("JOB 2") }
, however in my app (where scope is an instance variable) it’s currently more natural as is.
withContext
returns as soon as the lambda block completes. If you want to await all launched jobs in a certain scope, consider using coroutineScope instead.
1 Like
If true wouldn’t the following print
- Leave withContext()
- Delayed
instead of the reverse?
import kotlin.coroutines.EmptyCoroutineContext
suspend fun main() {
withContext(EmptyCoroutineContext) {
launch {
delay(1000L)
println("Delayed")
}
}
println("Leave withContext()")
}
withContext
and coroutineScope
don’t resume until all child jobs have finished.
job 2 can finish before or after job 1 finishes, but it will always finish before withContext
resumes.
I’ve had problems dealing with CoroutineScope instance variables where I use the wrong scope accidentally:
val myJob = scope.launch {
someFlow.launchIn(scope) { } // Oops, i mean't "this", not "scope", myJob will finish immediately
}
myJob.invokeOnCompletion { expectSomeFlowCollectionFinished() }
Perhaps you also are running into a similar situation using an unintended scope?