Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After a coroutine scope is cancel, can it still be used again?

When we have a coroutine scope, when it is canceled, can it be used again?

e.g. for the below, when I have scope.cancel, the scope.launch no longer work

    @Test
    fun testingLaunch() {
        val scope = MainScope()
        runBlocking {
            scope.cancel()
            scope.launch {
                try {
                    println("Start Launch 2")
                    delay(200)
                    println("End Launch 2")
                } catch (e: CancellationException) {
                    println("Cancellation Exception")
                }
            }.join()

            println("Finished")
        }
    }

Similarly, when we have scope.cancel before await called,

    @Test
    fun testingAsync() {
        val scope = MainScope()
        runBlocking {
            scope.cancel()
            val defer = scope.async {
                try {
                    println("Start Launch 2")
                    delay(200)
                    println("End Launch 2")
                } catch (e: CancellationException) {
                    println("Cancellation Exception")
                }
            }
            defer.await()
            println("Finished")
        }
    }

It will not execute. Instead, it will crash with

kotlinx.coroutines.JobCancellationException: Job was cancelled
; job=SupervisorJobImpl{Cancelled}@39529185
    at kotlinx.coroutines.JobSupport.cancel(JobSupport.kt:1579)
    at kotlinx.coroutines.CoroutineScopeKt.cancel(CoroutineScope.kt:217)
    at kotlinx.coroutines.CoroutineScopeKt.cancel$default(CoroutineScope.kt:215)
    at com.example.coroutinerevise.CoroutineExperiment$testingAsync$1.invokeSuspend(CoroutineExperiment.kt:241)
    at |b|b|b(Coroutine boundary.|b(|b)
    at kotlinx.coroutines.DeferredCoroutine.await$suspendImpl(Builders.common.kt:101)
    at com.example.coroutinerevise.CoroutineExperiment$testingAsync$1.invokeSuspend(CoroutineExperiment.kt:254)
Caused by: kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelled}@39529185
    at kotlinx.coroutines.JobSupport.cancel(JobSupport.kt:1579)
    at kotlinx.coroutines.CoroutineScopeKt.cancel(CoroutineScope.kt:217)
    at kotlinx.coroutines.CoroutineScopeKt.cancel$default(CoroutineScope.kt:215)
    at com.example.coroutinerevise.CoroutineExperiment$testingAsync$1.invokeSuspend(CoroutineExperiment.kt:241)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)

Is it true, a canceled coroutine scope cannot be used for launch or async anymore?

like image 313
Elye Avatar asked Jan 01 '21 10:01

Elye


People also ask

How do I cancel a coroutine job?

cancelAndJoin() // cancels the job and waits for its completion println("main: Now I can quit.") like the following example shows: val startTime = System. currentTimeMillis() val job = launch(Dispatchers.

Which coroutine job will be Cancelled automatically when a fragment view is destroyed?

ViewModelScope. A ViewModelScope is defined for each ViewModel in your app. Any coroutine launched in this scope is automatically canceled if the ViewModel is cleared.

Are coroutines lifecycle aware?

To use Kotlin Coroutine, we need to have the appropriate scope defined. The tricky bit of it is, we have to remember to create, and stop them. In view of that, the Google Android development team has provided us with some Coroutine Scopes that are aware of its lifecycle.

How do you wait for coroutine to finish Kotlin?

When we launch a coroutine in Kotlin using launch we are returned the resulting Job . We can wait for the coroutine to finish by calling join() on the Job.


1 Answers

Instead of using CoroutineScope for cancelling all of the launched jobs in it, you may want to use the underlying CoroutineContext with its cancelChildren() method which doesn't affect the Job state (which is not true for plain cancel() method) and allows to continue launching new coroutines after being invoked.

like image 51
Alex Bonel Avatar answered Sep 21 '22 04:09

Alex Bonel