Preparation of Hang function of Kotlin coroutine

1, Foreword

In the previous example, we know that we can start a co process through launch or async and control its life cycle. We also know that async can run in parallel. Other operations are recorded here

2, Delayed start process

A collaborative process can be defined in advance and then started when a certain condition is triggered, as follows:

private suspend fun doSomethingUsefulOne(): Int {
    delay(1000L) // pretend we are doing something useful here
    return 13
}

private suspend fun doSomethingUsefulTwo(): Int {
    delay(1000L) // pretend we are doing something useful here, too
    return 29
}
@Test
fun lazy(){
    runBlocking {
        val time = measureTimeMillis {
            val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
            val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
            // some computation
            one.start() // start the first one
            two.start() // start the second one
            println("The answer is ${one.await() + two.await()}")
        }
        println("Completed in $time ms")
    }
}

For delayed start functions, you can use job Start() or deffered await() to start, but in this case, first use job Start() starts and then uses deffered await() to get the result, because this will not lead to a parallel program, because await() becomes a serial program

3, Globalscope async

In fact, the official does not recommend directly using GlobalScope to start the collaboration process, because it is difficult to control. For example, we write an asynchronous task (asynchronous tasks are usually named with "... Async").

  • GlobalScope Is a subtle API, which may backfire in an extraordinary way. One of these ways will be explained below, so you must explicitly choose to use @ opt in (delectoroutinesapi:: class).
// The result type of somethingUsefulOneAsync is Deferred<Int>
@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulOneAsync() = GlobalScope.async {
    doSomethingUsefulOne()
}

// The result type of somethingUsefulTwoAsync is Deferred<Int>
@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulTwoAsync() = GlobalScope.async {
    doSomethingUsefulTwo()
}

Through globalscope Async started code can perform asynchronous operations anywhere, as follows

// The result type of somethingUsefulOneAsync is Deferred<Int>
@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulOneAsync() = GlobalScope.async {
    doSomethingUsefulOne()
}

// The result type of somethingUsefulTwoAsync is Deferred<Int>
@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulTwoAsync() = GlobalScope.async {
    doSomethingUsefulTwo()
}
@Test
fun taskAsync(){
    runBlocking {
        // note that we don't have `runBlocking` to the right of `main` in this example
            val time = measureTimeMillis {
                // we can initiate async actions outside of a coroutine
                val one = somethingUsefulOneAsync()
                val two = somethingUsefulTwoAsync()
                // but waiting for a result must involve either suspending or blocking.
                // here we use `runBlocking { ... }` to block the main thread while waiting for the result
                runBlocking {
                    println("The answer is ${one.await() + two.await()}")
                }
            }
            println("Completed in $time ms")
    }
}

There is no problem with the code itself. If the collaboration needs to be cancelled for some reason, such as an exception, in Val one = something usefuloneasync() and one If an error occurs in await (), somethingUsefulOneAsync() will run silently in the background even if cancel() is explicitly called. Here, you can use coroutine scope to solve this problem. Therefore, the following methods need to be modified

suspend fun concurrentSum(): Int = coroutineScope {
    val one = async { doSomethingUsefulOne() }
    val two = async { doSomethingUsefulTwo() }
    one.await() + two.await()
}
@Test
fun taskAsync(){
    runBlocking {
      val time = measureTimeMillis {
          println("The answer is ${concurrentSum()}")
      }
      println("Completed in $time ms")
    }
}

This is because the coroutineScope function is a suspended function. Where it is called, it needs to be bound to the scope using it. Therefore, when the scope is cancelled, the content of this function is also cancelled.

4, Reference link

  1. Write pending function

    https://kotlinlang.org/docs/composing-suspending-functions.html#lazily-started-async

Keywords: kotlin

Added by genesysmedia on Sun, 02 Jan 2022 08:02:05 +0200