bbaldino
09/23/2020, 5:13 PMfun my update() = runBlocking {
subscribers.forEach { url ->
launch(myIoPool.asCoroutineDispatcher()) {
try {
val resp = client.postJson(...)
<http://logger.info|logger.info>("Got response...")
} catch (e: HttpRequestTimeoutException) {
logger.error("Timed out...")
}
}
}
But I've now realized this is blocking until all the calls to launch
finish. What's the best way to fire-and-forget here? I think I've seen I can do this with GlobalScope.launch
(and getting rid of the runBlocking
), but from what I've read it seems like it's rarely a good idea to use that.araqnid
09/23/2020, 5:17 PMGlobalScope.launch
does basically what you need here - the scope is intended to cancel things that are still ongoing when the scope ends. You might consider that if your app has “start” and “stop” concepts, then that defines a scope which would be more precise than GlobalScope.bbaldino
09/23/2020, 5:17 PMGlobalScope
is the leaking, but this particular task basically runs for the lifetime of the app, so maybe it's not a worry?GlobalScope
?araqnid
09/23/2020, 6:57 PMCoroutineScope()
to create a new standalone scope (usually just a property initialiser) and then scope.cancel()
in your stop/close methodbbaldino
09/23/2020, 7:25 PMgildor
09/24/2020, 4:24 AMrarely a good idea to use thatYes, specifically because it can be used in cases as yours, global fire and forget background tasks Replacing GlobalScope with own scope can be better, but only if you really have some code which cancels it, otherwise it would be exactly the same
bbaldino
09/24/2020, 4:29 AMgildor
09/24/2020, 5:01 AMsuspend fun myUpdate(dispatcher: CoroutineDispatcher = myIoPool.asCoroutineDispatcher()) {
coroutineScope {
subscribers.forEach {
launch(dispatcher) {
try {
val resp = client.postJson(...)
<http://logger.info|logger.info>("Got response...")
} catch (e: HttpRequestTimeoutException) {
logger.error("Timed out...")
}
}
}
}
}
fun myBlockingUpdate() = runBlocking {
myUpdate()
}
fun myBackgroundUpdate(): Job {
GlobalScope.launch {
myUpdate()
}
}
suspend fun mySuspendUpdate() {
<http://logger.info|logger.info>("Before update")
myUpdate()
<http://logger.info|logger.info>("After update")
}
bbaldino
09/24/2020, 3:50 PMmyBackgroundUpdate
there, will there be two thread transitions? Calling thread -> GlobalScope thread -> io pool thread? Trying to make sure I'm understanding it correctly.araqnid
09/24/2020, 8:34 PMmyUpdate()
is just a suspend function to call. You can do GlobalScope.launch(myIoPool.asCoroutineDispatcher()) { }
to specify the scope and override coroutine context (i.e. the dispatcher here) in one go