I recently came across this code and do not understand the use of cancelAndJoin(). As I understand it, the extension function cancels the job and wait on its completion. So this coroutine would cancel itself and would never get any work done. But as it does my understanding must be wrong. Could someone explain this use of cancelAndJoin()?
job = viewModelScope.launch {
job?.cancelAndJoin()
while (isActive) {
//do some work
delay(1000L)
}
}
CodePudding user response:
As written, the code has a race condition. It looks like it's trying to cancel the previous job, but it is possible job
may already refer to itself by the time it executes that line of code.
If we copy the reference ensure we are cancelling the old job, it makes more sense:
val previousJob = job
job = viewModelScope.launch {
previousJob?.cancelAndJoin()
while (isActive) {
//do some work
delay(1000L)
}
}
It is cancelling the previous Job, and waiting to make sure it has reached a point of cancellation and actually exited, before the new coroutine continues with its work.
The reason to use cancelAndJoin()
instead of just cancel()
is if there are a series of non-cancellable function calls that you must wait for to avoid some other race condition.
Since delay()
cooperates with cancellation, the isActive
can be replaced with true
.