I have a simple app that needs to send heartbeat while main task is being executed
import kotlinx.coroutines.*
import java.net.URL
import kotlin.time.ExperimentalTime
import kotlin.time.measureTimedValue
@ExperimentalTime
fun main() {
runBlocking {
val job = launch {
while (isActive) {
println("send heartbeat")
delay(250)
}
}
println("Start loading")
val (payloadSize, duration) = measureTimedValue {
URL("https://sabnzbd.org/tests/internetspeed/20MB.bin")
.openConnection()
.getInputStream()
.use { it.readAllBytes().size }
}
println("Loaded $payloadSize bytes. Time $duration")
job.cancelAndJoin()
}
}
currently “heartbeat” is not being sent.
Do I understand it correctly, that delay in heartbeat job actually waits for some other coroutine to get suspended? My thread is actually being blocked by URL openConnection, so nothing happens.
Is the only way to provide dedicated threadpool to heartbeat job?
val job = launch(newSingleThreadContext("heartbeat")) {
while (isActive) {
println("send heartbeat")
delay(250)
}
}
that works.
Or
wrapping web call in withContext
works too
import kotlinx.coroutines.*
import java.net.URL
import kotlin.time.ExperimentalTime
import kotlin.time.measureTimedValue
@ObsoleteCoroutinesApi
@ExperimentalTime
fun main() {
runBlocking {
val job = launch {
while (isActive) {
println("send heartbeat")
delay(250)
}
}
withContext(Dispatchers.Default) {
println("Start loading")
val (payloadSize, duration) = measureTimedValue {
URL("https://sabnzbd.org/tests/internetspeed/20MB.bin")
.openConnection()
.getInputStream()
.use { it.readAllBytes().size }
}
println("Loaded $payloadSize bytes. Time $duration")
}
job.cancelAndJoin()
}
}
Is it because coroutines use Main thread dispatcher by default, and my heartbeat job is getting blocked in that thread?