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

vaskir

06/04/2020, 1:29 PM
Another question 🙂 Why is this warning? As I understand, it's the recommended way to wrap IO-bound blocking calls with
<http://Dispatchers.IO|Dispatchers.IO>
p

pawegio

06/04/2020, 1:31 PM
it’s blocking thread, but is it cancellable?
s

streetsofboston

06/04/2020, 1:34 PM
I think the linting that produces this warning is not able to look a few steps up the hierarchy and see the
<http://Dispatchers.IO|Dispatchers.IO>
there. Move the call to `withContext down to just before/around calling
process.waitFor
should get rid of the warning. Or otherwise, just suppress the warning 🙂
v

vaskir

06/04/2020, 1:37 PM
same
hmm. Is there a documentation for this warning? The algorithm?
waitFor
is not cancellable.
It's just throw if timed out
s

streetsofboston

06/04/2020, 1:38 PM
This lint warning is produced if the call is declared to be able to throw an IOException and this call is not directly wrapped inside a
withContext(<http://Dispatchers.IO|Dispatchers.IO>)
call.
It produces false warnings if the dispatcher was switched to the IO one earlier and if your code injects the dispatchers and not ‘hard-code’ the Dispacthers.IO. I has nothing to do with being cancellable or not.
👌 1
v

vaskir

06/04/2020, 1:40 PM
BTW, maybe there's a well behaving, idiomatic way to run a process, with timeout and cancellation?
I'm using val process = ProcessBuilder(*parts.toTypedArray())   .directory(workingDir)   .redirectOutput(ProcessBuilder.Redirect.PIPE)   .redirectError(ProcessBuilder.Redirect.PIPE)   .start()
s

streetsofboston

06/04/2020, 1:41 PM
You can’t cancel a blocking call. At best you can interrupt the thread that is blocked but that can be dangerous
You can cancel a suspending call, though, but that is different 🙂
v

vaskir

06/04/2020, 1:42 PM
Yes, I understand.
m

marstran

06/04/2020, 1:43 PM
Do you really need the separate call to
withContext
? Can't you just do this:
Copy code
launch(<http://Dispatchers.IO|Dispatchers.IO>) {
    process.waitFor(....)
}
👆🏻 1
v

vaskir

06/04/2020, 1:43 PM
I think about a process runner, which, being cancelled, kill the process or something like this.
@marstran aha! The warning has gone.
But I think
withContext
is what is recommended to use, isn't it?
s

streetsofboston

06/04/2020, 1:45 PM
If you want to cancel something:
Copy code
suspendCancellableCoroutine<Unit> { cont ->
    val handle = startBlockingProcess(....)
    cont.invokeOnCancelation { handle.cancel() }
    cont.resume(Unit)
}
(assuming
handle
represents a process that can be cancelled by calling
cancel()
or something similar on it)
v

vaskir

06/04/2020, 1:45 PM
aha. I just read about this function yesterday 🙂
thanks.
s

streetsofboston

06/04/2020, 1:48 PM
You may need to do
handle.awaitResult()
or
handle.join()
or what-ever would be the correct function name, just before calling
cont.resume(Unit)
v

vaskir

06/04/2020, 2:42 PM
Should I handle exceptions inside it?
s

streetsofboston

06/04/2020, 2:43 PM
Yup, catch them and do
cont.resumeWithException(e)
v

vaskir

06/04/2020, 2:44 PM
ok
s

streetsofboston

06/04/2020, 2:45 PM
But this depends on how you model your app’s data model. You can catch the exception and then handled it by returning an error-value instead (
cont.resume(errorData)
)
v

vaskir

06/04/2020, 2:47 PM
got it
8 Views