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

Hexa

05/09/2019, 9:43 PM
Is there a better way to write this?
Copy code
runBlocking {
        coroutineScope {
            withTimeoutOrNull(10000L){ // wait time mili seconds
                val a: Deferred<Unit> = async { s.deleteItem(xyz) }
                 val b: Deferred<Unit> = async { s.deleteItem(abc) }

                      launch {
                           a.await()
                            b.await()
                        }   
                 }
          }
  }
My async calls returns Deferred<Unit> but I thought it might be better to explicitly call await() on each of them as this would force the tasks to go back in the main thread. I prefer to do it this way because I'm using AWS lambda and I read somewhere that the lambda can freeze/terminated if the tasks stays in the background thread, see https://stackoverflow.com/a/39668749
g

gildor

05/10/2019, 1:06 AM
You don't need launch
Also looks that you don't need any result, so you can just do: launch { s.deleteItem() }
Because you use withTimeout function, you also don't need coroutineContext, you already have scope
So, essentially, excluding runBlocking, your code is just:
Copy code
withTimeoutOrNull(10000L) {
   launch { s.deleteItem(xyz) }
   launch { s.deleteItem(abc) }
}
For real product ready code you should also remember do not swallow timeout exception error (handle null in this case) and also handle error, because withTimeoutOrNull handles only timeout exceptions
Not really sure what you mean about threading in this case, because await() has nothing to do with thread switching, also in you example with runBlocking you already use thread from which runBlocking is executing and async or launch will not be dispatched on some background thread, it will use blocked thread, so if you want to run delete operation on another thread you have to specify dispatcher explicitly, for example Default or IO (if delete operation is blocking)
Copy code
runBlocking {
  withTimeoutOrNull(10000L) {
   launch(<http://Dispatchers.IO|Dispatchers.IO>) { s.deleteItem(xyz) }
   launch(<http://Dispatchers.IO|Dispatchers.IO>) { s.deleteItem(abc) }
  }
}
Something like that
h

Hexa

05/10/2019, 8:46 AM
thanks @gildor, I'm a bit confuse. Will the runBlocking code wait for the coroutine to finish and then goes back to the main thread? Also I read somewhere that we should never use runBlocking in production, is this true? see https://stackoverflow.com/a/52332499
g

gildor

05/10/2019, 3:34 PM
Yes, runBlocking creates new coroutine scope, so it means that it will wait child coroutines before return
runBlocking is just an adapter between blocking and suspend code, if you have some existing async API, than better to write suspend adapater for it and do not use runBlocking, but sometimes it's just the only way, for example if you have command like app, you should block main thread to avoid program to finish while your async code is running, or maybe it's also your case for aws lambda function
This stackowerflow is a bit misleading, also they discuss mostly Android, not other usecases outside of UI programming
h

Hexa

05/13/2019, 12:46 PM
Thanks @gildor, it looks like runBlocking is exactly what I need then.
7 Views