Hi, I have a problem that i would like to solve us...
# coroutines
s
Hi, I have a problem that i would like to solve using coroutines but haven’t found a successful way to do it. I have a while loop, that reads input from an input stream (bluetooth socket on android) until a specific number of words have been received. However, the while loop could run forever incase the specific number of words has not been sent (and the socket connection is still active). To mitigate this, i would like to have two operations running, one that runs a timeout (delay) and the other to do the actual work. These operations would run concurrently and i would be interested in getting the completion of the fastest operation. This way i can be sure that i would not wait for a result forever and i can handle the exception. One approach i tried was using withTimeout, but it would never really timeout (not sure why)
Copy code
withTimeout(20000) {
    try{
        while (true) {
            // read input from socket and exit while block when exception is thrown 
            // or expected data has been received   
        }
    }catch(e: Exception) {
        // Handle the exception here
    }
}
I also tried to use this, but the code within`scope.launch` was never executed but the timeout worked as expected
Copy code
val scope: CoroutineScope = CoroutineScope(Job() + <http://Dispatchers.IO|Dispatchers.IO>)
withTimeout(20000){
    suspendCancellableCoroutine<String>{ continuation ->

        continuation.invokeOnCancellation {
            // Handle my exception here
        }
        
        scope.launch {
            while (true) {
                // read input from socket and exit while block when exception is thrown 
                // or expected data has been received   
            }
        }
    }
}
Could someone please help give me some pointers in what i might be missing or even perhaps a better way to approach this?
z
Coroutine cancellation is cooperative. If your coroutine never checks if it's cancelled, it will never stop. Change your while loop to
while(isActive)
and wrap your IO in
runInterruptible
(https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-interruptible.html
s
hi @Zach Klippenstein (he/him) [MOD],
runInterruptible
doesn’t seem to exist for me 🤔
z
What version of coroutines are you on?
s
i’m on
1.3.7
currently
z
It was released in 1.3.6. Are you writing common code or jvm?
I think it only exists for jvm
s
ahh…i am targeting android, thats probably why it doesn’t exist
z
Android is considered jvm as far as Kotlin is concerned, that should still work
Until you figure out why it's not working, you can just set a short timeout on your read operation and rely on the
isActive
check. It's slightly more wasteful but still better than not cancelling at all
s
i was able to get
runInterruptible
working but it did not actually cancel the block 🤔