Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to launch a Kotlin coroutine in a `suspend fun` that uses the current parent Scope?

Tags:

How can I launch a coroutine from a suspend function and have it use the current Scope? (so that the Scope doesn't end until the launched coroutine also ends)

I'd like to write something like the following –

import kotlinx.coroutines.*

fun main() = runBlocking { // this: CoroutineScope
    go()
}

suspend fun go() {
    launch {
        println("go!")
    }
}

But this has a syntax error: "Unresolved Reference: launch". It seems launch must be run in one of the following ways –

GlobalScope.launch {
    println("Go!")
}

Or

runBlocking {
    launch {
        println("Go!")
    }
}

Or

withContext(Dispatchers.Default) {
    launch {
        println("Go!")
    }
}

Or

coroutineScope {
    launch {
        println("Go!")
    }
}

None of these alternatives does what I need. Either the code "blocks" instead of "spawning", or it spawns but the parent scope won't wait for its completion before the parent scope itself ends.

I need it to "spawn" (launch) in the current parent coroutine scope, and that parent scope should wait for the spawned coroutine to finish before it ends itself.

I expected that a simple launch inside a suspend fun would be valid and use its parent scope.

I'm using Kotlin 1.3 and cotlinx-coroutines-core:1.0.1.

like image 496
Rusty Fieldstone Avatar asked Dec 20 '18 05:12

Rusty Fieldstone


People also ask

How do I launch coroutine Kotlin?

The simplest way to create a coroutine is by calling the launch builder on a specified scope. It Launches a new coroutine without blocking the current thread and returns a reference to the coroutine as a Job. The coroutine is canceled when the resulting job is canceled. The launch doesn't return any result.

How do I make a Kotlin coroutine scope?

The easiest way to create a coroutine scope object is by using the CoroutineScope factory function 1. It creates a scope with provided context (and an additional Job for structured concurrency if no job is already part of the context).

Are Kotlin coroutines concurrent?

Kotlin coroutines & structured concurrencyIn Kotlin, we can create coroutines using builders such as launch and async , which return a Job instance. This Job may further contain nested coroutine builders that create children Job instances that are computed concurrently.

What is the difference between launch and async in Kotlin coroutines?

The launch launches a new coroutine concurrently with the rest of the code, which continues to work independently. The async creates a coroutine and can return the result of the asynchronous task.

How can we use coroutinescopes in Kotlin?

How can we use CoroutineScopes in Kotlin? Kotlin’s Coroutines allow the use of suspend functions, Channels and Flows and they all operate in the context of a so-called CoroutineScope. How can we tie it to the lifecycle management of our own components?

What is the use of suspend function in Kotlin?

Suspend Function In Kotlin. Suspend function is a function that could be started, paused, and resume. One of the most important points to remember about the suspend functions is that they are only allowed to be called from a coroutine or another suspend function. An example is given below, in which we have tried to call the delay() function ...

What is coroutinecontext in Kotlin?

Coroutines always execute in some context represented by a value of the CoroutineContext type, defined in the Kotlin standard library. The coroutine context is a set of various elements. The main elements are the Job of the coroutine, which we've seen before, and its dispatcher, which is covered in this section.

What is the use of suspend () function in coroutine?

Suspending functions can be used inside coroutines just like regular functions, but their additional feature is that they can, in turn, use other suspending functions (like delay in this example) to suspend execution of a coroutine. println("World!") You can get the full code here.


1 Answers

You should make the function go an extension function of CoroutineScope:

fun main() = runBlocking {
    go()
    go()
    go()
    println("End")
}

fun CoroutineScope.go() = launch {
    println("go!")
}

Read this article to understand why it is not a good idea to start in a suspend functions other coroutines without creating a new coroutineScope{}.

The convention is: In a suspend functions call other suspend functions and create a new CoroutineScope, if you need to start parallel coroutines. The result is, that the coroutine will only return, when all newly started coroutines have finished (structured concurrency).

On the other side, if you need to start new coroutines without knowing the scope, You create an extensions function of CoroutineScope, which itself it not suspendable. Now the caller can decide which scope should be used.

like image 65
Rene Avatar answered Oct 21 '22 21:10

Rene