For the sake of completeness, I should mention tha...
# coroutines
p
For the sake of completeness, I should mention that cancellation is not only possible at suspension points, you can also check
isActive
yourself to stop execution -- all of Kotlin's suspending functions do that so they also enable cancellation
d
Hi @petersommerhoff, I'm experimenting coroutines right now and I have a little discrepation with what I learned in courses. Do you mind if I ask you a clarification?
p
Sure, I'm glad to help if I can
d
Here is the code
launch(UI) { deferred = async(CommonPool) { while (true) { Thread.sleep(2000) Log.i("Coroutines", "Hello") } } }
When I call deferred.cancel() for example in a button (Android), Log.i does not stop printing. What am I missing?
After deferred.cancel() deferred.isActive is actually false
Then I put that code in a suspended function: private suspend fun loop() { while (true) { Thread.sleep(2000) Log.i("Coroutines", "Hello") } }
Same result. Thank you for your kindness 😄
p
@Dario Pellegrini Cancellation is cooperative, this means every coroutine must support cancellation itself (in contrast to preemptive cancellation of threads, they are forced to cancel). In your first example, there is no call to another suspending function and you don't check
isActive
manually either, so that coroutine is not cooperative. At no point can it cancel. If you use
delay
instead of
Thread.sleep
, it becomes cooperative and can be cancelled.
In your second example, the
suspend
modifier is redundant, it's just a normal function without any suspending calls. Again, this changes if you use the non-blocking
delay
instead of the blocking
Thread.sleep
d
Ok let me know if I got the point. If instead of that Thread.sleed I would have a network request like
fun getStuff(): Deferred<String> = async { ... }
I should do
Copy code
deferred = async(CommonPool) {
 while (true) {
   Log.i("Coroutines", get().await())
 }
}
Is that correct?
(I have edited the commen a thousands times to fit the code :D)
p
Well, now that you're calling
await()
(which I assume is suspending), it is cancellable 👍 But I'm not sure why you would call
await()
on the same future again and again in a
while (true)
loop.
You may want to read the cancellation part of the coroutines guide: https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md#cancellation-and-timeouts
d
The code is actually
Copy code
job = launch(UI) {
            while (true) {
                updateUI(get().await())
            }
        }
Had to update UI constantly using a service (IoT board).
Maybe using a repeat was better
g
your latest code snippet is cancellable, but I would use
while(isActive)
instead, on practice there is no difference (when coroutines cancelled next call of await will stop loop), but just more explicit approach
👍 1
If instead of that Thread.sleed I would have a network request
It’s fine if you have suspenstion point, but don’t forget to cancel network request on coroutine cancallation, your callback adapter
await()
should handle this, otherwise network request continued after coroutines cancelation