`runblocking`'s documentation says: "This function...
# coroutines
n
`runblocking`'s documentation says: "This function should not be used from a coroutine" My question is how can I detect that some code is running in a coroutine? Eg.
fun main() {
runBlocking {
suspendFun()
}
}
suspend fun suspendFun() {
normalFun()
}
fun normalFun() {
val runningInCoroutine = ???
check(!runningInCoroutine)
runBlocking {
...
}
}
j
You can't really "detect" it in a general way. But
runBlocking
is a way to give up when you have no choice but to bridge a blocking API with suspending one. So you shouldn't really use it from any non suspend function, you should try other options first. Normally in the case you're showing, you should try to make your own function suspend, and go up the stack until you hit a roadblock. If you end up in a place where you don't control the caller, you can assume it's not using coroutines and use
runBlocking
.
πŸ‘† 2
πŸ‘ 2
πŸ‘πŸ» 1
😞 2
e
yep. there is no way to determine if you're in a non-suspend function called from a suspend function, unless you use some non-portable mechanisms to look up the call stack. but the you should only ever use
runBlocking
at specific entry points (such as
main
), which then avoids this issue entirely.
πŸ‘ 4
😞 2
πŸ‘πŸ» 1
y
I'm guessing blockhound with coroutines helper could identify these problems. Not working yet on Android IIUC https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/index.html
e
oh yes, I was thinking of -javaagent as a non-portable mechanism, but if you exclude Android it works on basically all JVMs
there's no
fun main()
on android anyway :D
come to think of it, it would be interesting to inject a call to StrictMode.noteSlowCall() in
runBlocking()
on Android, so that you could enable a similar sort of runtime check, but unfortunately it doesn't look like there's a built-in extension point to do that. could be worth filing a feature request
πŸ‘πŸ» 1
a
If you ever find yourself typing
runBlocking
on Android and you're not doing it in a method annotated
@Test
you're probably on the wrong path.
☝️ 2
πŸ‘ 4
βž• 4
a
Is there a recommended alternative when (eventually) calling into a suspending Kotlin function from a Java background thread in a mixed Java/Kotlin project? (obviously the Java code would have to call into a Kotlin helper to be able to call runBlocking at all)
e
use a scope that matches the thread's lifecycle
j
Not really, I mean it depends on the behaviour you're looking for. After all, if the Java thread should block to wait for an answer, there aren't any alternatives anyway, so this would be one of the rare good cases for
runBlocking
. However, if it's ok for the Java thread to just start something asynchronous that returns immediately, your Kotlin helper could launch the coroutine in a particular coroutine scope.
πŸ‘ 1
a
Yeah, in this case it’s ancient Java code that is designed to fire up worker threads that block for a result. Connecting it with our coroutine-aware repositories seems to demand
runBlocking
.