Reputation: 73721
I have a few suspend functions that make a network call in my WorkManager
that I am trying to get to run in parallel using Coroutines so I was trying to use async
in them but they seem to still be executed sequentially.
Example:
suspend fun call1() = withContext(Dispatchers.IO){
async{
Log.d(TAG,"Call 1 started")
delay(2000)
Log.d(TAG,"Call 1 fiished")
}
}
suspend fun call2() = withContext(Dispatchers.IO){
async{
Log.d(TAG,"Call 2 started")
delay(5000)
Log.d(TAG,"Call 2 finished")
}
}
suspend fun call3() = withContext(Dispatchers.IO){
async{
Log.d(TAG,"Call 3 started")
delay(1000)
Log.d(TAG,"Call 3 finished")
}
}
I call them like this
override suspend fun doWork(): Result{
setForeground(createForegroundInfo())
call1()
call2()
call3()
return Result.success()
}
When I run this I see the log messages show up as in order just as they are called and the next call does not start until the previous one finishes. What I was expecting is call3
to finish first then call1
and finally call2
but it just gets call1, call2, call3.
What am I missing to get these to execute in parallel?
Upvotes: 2
Views: 1316
Reputation: 22832
If you create a new scope for each one, they would be launched in parallel:
suspend fun call1() = CoroutineScope(Dispatchers.IO).launch {
Log.d(TAG, "Call 1 started")
delay(2000)
Log.d(TAG, "Call 1 fiished")
}
Although the above solution works in parallel, but you can not keep track of the coroutines which causes a possible execution leak. To preserve structural concurrency it's better to do it like the following:
suspend fun call1() = withContext(Dispatchers.IO) {
Log.d(TAG, "Call 1 started")
delay(2000)
Log.d(TAG, "Call 1 fiished")
}
suspend fun call2() = withContext(Dispatchers.IO) {
Log.d(TAG, "Call 2 started")
delay(5000)
Log.d(TAG, "Call 2 finished")
}
suspend fun call3() = withContext(Dispatchers.IO) {
Log.d(TAG, "Call 3 started")
delay(1000)
Log.d(TAG, "Call 3 finished")
}
And then:
override suspend fun doWork(): Result{
setForeground(createForegroundInfo())
coroutineScope {
launch { call1() }
launch { call2() }
launch { call3() }
}
Log.d(TAG, "After all finishings")
return Result.success()
}
Upvotes: 3