Best way to launch a coroutine in a suspend functi...
# coroutines
l
Best way to launch a coroutine in a suspend function? See thread.
I need to launch a coroutine to do some parallel task in a suspend function, and I figure out three ways to implement it. But all of them have problems. SoI want to know if there’s some good ways to implement it? 1. use
GlobalScope
, seems it violates the rule of “structure concurrency”.
Copy code
suspend fun someSuspendFunction() {
       GlobalScope.launch {
           // parallel task
       }

       // other logic
   }
2. use
coroutineScope
, seems good, but
coroutineScope
will suspend until the inside coroutines finished, so it can’t meet my requirement.
Copy code
suspend fun someSuspendFunction() {
       coroutineScope {
           launch {
   // parallel task
           }
       }

       // other logic
   }
3. pass a
CoroutineScope
from upstream, it works, but seems a little bit complex.
Copy code
suspend fun someSuspendFunction(scope: CoroutineScope) {
       scope.launch {

       }

       // other logic
   }
Any good ways?
s
1 and 3 are basically the same (3 is like when when you pass GlobalScope as value for the scope parameter). But you have to make a decision. Either you want to do something in parallel that have different lifecycles (suspend function's CoroutineScope and the CoroutineScope you pass as parameter) or you want to maintain Structured Concurrency. You can't eat your cake and have it too 😀
For 2), if you want 'other logic' to be executed in parallel with code inside the 'launch', move 'other logic' inside coroutineScope's lambda.
l
if you want ‘other logic’ to be executed in parallel with code inside the ‘launch’, move ‘other logic’ inside coroutineScope’s lambda.
Oh, thanks a lot! I try it and I think this is just what I want. 😀
👍 1
j
3 is the way. It's how structured concurrency is supposed to work!
s
Option 3. is not the way. It'll break structured concurrency and it violates the general principle (code-style) that a function either is
suspend
and it suspends, or it takes a
CoroutineScope
(either as its extension-parameter or as a regular parameter) and it returns immediately. Option 3. would be ok only if it is clearly documented that the suspend function will suspend until its work is done but that a parallel task is being kicked off that may or may not finish before the suspend fun resumes.
j
You are right
Didn't notice that 3 was marked suspend
s
How about 3 as a non suspending function that returns immediately?
Copy code
fun someRegularFunction1(scope: CoroutineScope) {
        scope.launch {
            // parallel task
        }
        scope.launch {
            // other logic
        }
    }

    fun someRegularFunction2(scope: CoroutineScope) = scope.launch {
        launch {
            // parallel task
        }
        launch {
            // other logic
        }
    }
or as a suspend function returning the parallel task Job?
Copy code
suspend fun someSuspendFunction(scope: CoroutineScope): Job {
        val job = scope.launch {
            // parallel task
        }

        // other logic
        
        return job
    }