https://kotlinlang.org logo
Title
p

petersommerhoff

04/24/2018, 7:58 AM
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

Dario Pellegrini

04/24/2018, 8:19 AM
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

petersommerhoff

04/24/2018, 8:19 AM
Sure, I'm glad to help if I can
d

Dario Pellegrini

04/24/2018, 8:22 AM
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

petersommerhoff

04/24/2018, 8:37 AM
@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

Dario Pellegrini

04/24/2018, 10:11 AM
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
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

petersommerhoff

04/24/2018, 11:10 AM
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

Dario Pellegrini

04/24/2018, 11:37 AM
The code is actually
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

gildor

04/24/2018, 3:42 PM
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