Is the following example a good use case for the `...
# coroutines
e
Is the following example a good use case for the
NonCancellable
(https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-non-cancellable.html) coroutine context? Just before my UI finishes (Android activity
onDestroy
), I want to complete a certain async task and be sure that it finishes before the coroutine scope's (
viewModelScope
) cancellation completes. So on the scope I call
scope.launch(NonCancellable) { /* Do async task that must complete */ }
. If that task takes long enough for the the scope to be cancelled before the task completes, then this will not cancel the task, but let it run. So the scope will not complete until this task finishes. Did I just introduce a bug or make use of a feature? Are there safer alternatives that guarantee task completion? (🤖 bonus question: in theory, if that task takes, say, a minute, or an hour, what would eventually happen to my process?)
d
I think you want to do this.
Copy code
scope.launch {
    withContext(NonCancellable) {
        // Code that must complete once started.
    }
}
To make sure the parent scope waits for cancellation. Passing
NonCancellable
directly into
launch
breaks the parent-child relationship.
e
Normally, yes: you don't want to provide a new
Job
in
launch() {}
. But since the purpose of
NonCancellable
is to break the cancellation chain from parent to child, what is the problem? Why should I instead use
launch { withContext(NonCancellable) {} }
?
d
Maybe it doesn't matter in your case, but if you have this.
Copy code
// Ex 1
coroutineScope {
    launch(NonCancellable) {
        delay(5000)
    }
}

// Ex 2
coroutineScope {
    launch {
        withContext(NonCancellable) {
            delay(5000)
        }
    }
}
Ex1 will return immediately and Ex2 will return after 5000ms. But the delay will still "run" in either case.
e
I don't really understand your example. I tried using it here: https://pl.kotl.in/dcnFC7rZF But as you can see, both the launched coroutines complete at the same time, and return immediately (see the third elapsed time)
Which is, AFAIK, how it should behave:
launch
is fire and forget, i.e. return quickly
t
This post might be helpful. https://link.medium.com/IW0nkFprw5 It talks about operation lifetimes that outlives the scope of the view. Recommendation is to provide your own scope, even if that scope matches the process lifetime like
GlobalScope
. As to what what would happen to your process if the NonCancelable took a long time, I don't think it would make any difference. You might cause a leak until it's finished, but ultimately the if the process shuts down then it would stop running this task. Similar to if you had a long operation running in
GlobalScope
e
Thanks for the article
👍 1
d
Of course the coroutines finish at the same time, the code is just about the same. I'm trying to highlight that the parent will not wait for the child. https://pl.kotl.in/8xW1nNwmx
e
Very clear, thanks your example