The Programmers Guide To Kotlin - Coroutines |
Written by Mike James | |||||||
Monday, 07 June 2021 | |||||||
Page 3 of 3
Blocking With coroutineScopeNotice that launch is a non-blocking call that creates and adds a coroutine to the queue. If you want to create a blocking call to create and add a coroutine then use the coroutineScope function. This creates a new scope that only unblocks when all of the coroutines that have been created within it have finished. For example, if you change launch to coroutineScope: import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay you will see: main start Coroutine1 start Coroutine2 start 12345678910 Coroutine2 finishing 1234567891011121314151617181920 Coroutine1 finishing main stopped Notice that now Coroutine1 is suspended until Coroutine2 has finished even if Coroutine2 suspends itself repeatedly for 1ms. This is the idea of structured asynchronous code. Each coroutineScope block does not move on until all of the coroutines it contains have finished. You can also use the block to cancel, or otherwise modify, all of the coroutines it contains and if a contained coroutine fails then the entire block fails, more of this later. You can use coroutineScope blocks to organize and control your coroutines. At this point you might be wondering what the difference is between coroutineScope and runBlocking? The answer is that you can use runBlocking from a non-suspending, i.e. a standard function, but you can only use coroutineScope from within another suspending function. In other words, you can use runBlocking to get coroutines started from the main function, but after that you should use coroutineScope to repurpose the thread. Sequential & ConcurrentNow we have two ways to run coroutines – launch which places a coroutine in the dispatcher’s queue and returns, and coroutineScope which does the same but then waits until the coroutine has completed. This means you can now schedule coroutines to run sequentially or concurrently. In the case of sequentially: runBlocking { coroutineScope { co1() } the outer coroutine places co1 and then co2 into the queue. The co1 function is run when the outer coroutine ends and runs to completion, even if it is suspended multiple times, before the co2 function is run. The runBlocking doesn’t return until both co1 and co2 have completed. If the two functions being called are marked as suspend you can drop the use of coroutineScope and simply call the functions: runBlocking { co1() co2() } This works because both functions can contain suspension points and are therefore run asynchronously even if they occupy a single position in the dispatcher’s queue. That is, co2 will not run until co1 has finished even if it suspends. This form is slightly more efficient but only works with functions that have the suspend modifier and the functions are treated as a single job. The alternative is concurrently: runBlocking { launch { co1() } launch { co2() } } In this case co1 and co2 are added to the dispatcher’s queue as before and in a single threaded dispatcher co1 is started when the outer coroutine is finished. The difference is that now co2 is started is co1 suspends and co1 only restarts if co2 suspends or completes. When the runBlocking is finished you can say that co1 and co2 are complete but not the order in which they finished. In book but not in this extract:
Summary
This article is an extract from: Programmer's Guide To Kotlin Third Edition
You can buy it from: Amazon Contents
<ASIN:B0D8H4N8SK> To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.
Comments
or email your comment to: comments@i-programmer.info |
|||||||
Last Updated ( Monday, 07 June 2021 ) |