Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Launching coroutines from a suspended function

Given we have a suspending function but this is not a CoroutineScope, how can we launch other coroutines such that those are associated with the current scope of whatever runs this suspending function?

like image 271
vach Avatar asked Mar 11 '19 13:03

vach


People also ask

Can coroutines be suspended and resumed?

If you notice the functions closely, they can be used to resume the coroutine with a return value or with an exception if an error had occurred while the function was suspended. This way, a function could be started, paused, and resume with the help of Continuation. We just have to use the suspend keyword.

How coroutines are suspended?

Which coroutine gets suspended? The outer async starts a coroutine. When it calls computation() , the inner async starts a second coroutine. Then, the call to await() suspends the execution of the outer async coroutine, until the execution of the inner async 's coroutine is over.

Why do we use Suspend function in Kotlin?

SUSPENDING: Function A, while has started, could be suspended, and let Function B execute, then only resume later. The thread is not locked by Function A. In short, the suspend function is a function that could be started, paused and resume, (and pause and resume…. if wanted repeatedly) and then end.

What is the function used for launching for coroutines?

Async Function Async is also used to start the coroutines, but it blocks the main thread at the entry point of the await() function in the program.


1 Answers

Every suspendable function has access to the global variable coroutineContext which you can trivially wrap in CoroutineScope, but that is not its intended purpose. It's there so you can check at any point whether your coroutine was cancelled, reach the debug info like the job name, etc.

In the words of Roman Elizarov in his recent Medium post:

suspend fun doNotDoThis() {
    CoroutineScope(coroutineContext).launch {
        println("I'm confused")
    }
}

Do not do this!

A suspendable function should not fire off concurrent work that may go on after it returns. It should only use concurrency to achieve parallel decomposition of a task, and that means it will wait for all the child coroutines to complete.

You should decide to either use a plain function that is the receiver of CoroutineScope (signaling the intention to launch concurrent work) or use a suspendable function that awaits on the completion of all the work it initiated.

So, if you want parallel decomposition, then use a coroutineScope or, possibly a supervisorScope block:

coroutineScope {
    launch { 
        // ... task to run in the background
    }
    // ... more work while the launched task runs in parallel
}
// All work done by the time we reach this line

coroutineScope is a suspendable function and it won't complete until all the coroutines it launched complete.

like image 113
Marko Topolnik Avatar answered Oct 17 '22 04:10

Marko Topolnik