https://kotlinlang.org logo
#coroutines
Title
# coroutines
m

matej

06/23/2020, 12:58 PM
How can I get my
Job
(Kotlin native) to finish whatever it was doing after calling
cancel()
? Assume the simple example of a `launch`ed
Job
that does something in a
while(isActive)
loop. When it exits the loop it would need to run a few more lines of cleanup before it completes. As it stands, after calling
cancel()
my job is getting terminated outright, and the lines after the while loop never get executed. I'm left scratching my head.
d

Dennis Schröder

06/23/2020, 1:13 PM
Here is a really good talk about the lifecycle handling of coroutines from the latest KotlinConf

https://www.youtube.com/watch?v=w0kfnydnFWI

That will answer your question.
👍 1
s

streetsofboston

06/23/2020, 1:22 PM
Copy code
try {
   while (isActive) {
    ...
   }
} finally {
   // a few more lines here, clean up, etc
   ...
}
m

matej

06/23/2020, 1:25 PM
I understand what my problem is now. I cannot call any utility function that throws CancellationException past the point the Job was cancelled (like delay, for example), puts me in a pickle. The behavior I am after is rather that I can signal to the Job/Coroutine that "hey, it's time to wrap things up, but do what you have to do", not "hey, you've been cancelled, and you may not do anything for which you need a coroutine in the first place anymore"
m

Manuel Wrage

06/23/2020, 1:28 PM
I guess you're looking for withContext(NonCancellable) {...}
s

streetsofboston

06/23/2020, 1:31 PM
Either what @Manuel Wrage said or do the clean-up, that may involve calling other suspend functions, within a separate CoroutineScope.
Copy code
try {
   while (isActive) {
    ...
   }
} finally {
   cleanUpScope.launch { /* a few more lines here, clean up, etc */ }
}
m

matej

06/23/2020, 2:12 PM
@Manuel Wrage Almost, but not quite, I still need the outside code to be able to signal to the Job that it should wrap things up. With NonCancellable, isActive just always returns true, if I understand it correctly. I would have to come up with my own version of NonCancellable that allows that, a sort of SoftCancellable. @streetsofboston That might do the trick, I'll just have to see what would be the best way to define the cleanUpScope, to keep the code reliable and testable. Thank you all! This was very helpful.
@Manuel Wrage Turns out this is exactly it! I misunderstood you the first time. Basically, doing what @streetsofboston said, but with you suggestion of NonCancellable worked like a charm:
Copy code
try {
   while (isActive) {
    ...
   }
} finally {
   withContext(NonCancellable) { /* a few more lines here, clean up, etc */ }
}
With the added benefit that calling
join
on the main job also seems to work as expected, and waits for the NonCancellable bit to complete.
👍 2
5 Views