=================
== The Archive ==
=================

[Kotlin Coroutines] 11장. 코루틴 스코프 함수

코루틴 스코프 함수가 소개되기 전에 사용한 방법들

coroutineScope

1
2
3
4
5
6
7
8
9
public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return suspendCoroutineUninterceptedOrReturn { uCont ->
        val coroutine = ScopeCoroutine(uCont.context, uCont)
        coroutine.startUndispatchedOrReturn(coroutine, block)
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
fun main() =
    runBlocking {
        val a =
            coroutineScope {
                delay(1000)
                10
            }
        println("a is calculated")
        val b =
            coroutineScope {
                delay(1000)
                20
            }
        println(a) // 10
        println(b) // 20
    }

// (1초 후)
// a is calculated
// (1초 후)
// 10
// 20
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private suspend fun longTask() =
    coroutineScope {
        launch {
            delay(1000)
            val name = coroutineContext[CoroutineName]?.name
            println("[$name] Finished task 1")
        }
        launch {
            delay(2000)
            val name = coroutineContext[CoroutineName]?.name
            println("[$name] Finished task 2")
        }
    }

fun main() =
    runBlocking(CoroutineName("Parent")) {
        println("Before")
        longTask()
        println("After")
    }

// Before
// (1 sec)
// [Parent] Finished task 1
// (1 sec)
// [Parent] Finished task 2
// After
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private suspend fun longTask() =
    coroutineScope {
        launch {
            delay(1000)
            val name = coroutineContext[CoroutineName]?.name
            println("[$name] Finished task 1")
        }
        launch {
            delay(2000)
            val name = coroutineContext[CoroutineName]?.name
            println("[$name] Finished task 2")
        }
    }

fun main(): Unit =
    runBlocking {
        val job =
            launch(CoroutineName("Parent")) {
                longTask()
            }
        delay(1500)
        job.cancel()
    }

// [Parent] Finished task 1

// Process finished with exit code 0

코루틴 스코프 (중단) 함수

| 코루틴 빌더

(runBlocking 제외)코루틴 스코프 함수
launch, async, producecoroutineScope, supervisorScope, withContext, withTimeout
CoroutineScope 의 확장 함수중단 함수
CoroutineScope 리시버의 코루틴 컨텍스트를 사용중단 함수의 컨티뉴에이션 객체가 가진 코루틴 컨텍스트를 사용
예외는 Job 을 통해 부모로 전파됨일반 함수와 같은 방식으로 예외를 던짐
비동기인 코루틴을 시작함호출된 지점에서 코루틴을 시작함(Starts a coroutine that is called in-place.)

withContext

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private fun CoroutineScope.log(text: String) {
    val name = this.coroutineContext[CoroutineName]?.name
    println("[$name] $text")
}

fun main() =
    runBlocking(CoroutineName("Parent")) {
        log("Before")

        withContext(CoroutineName("Child 1")) {
            delay(1000)
            log("Hello 1")
        }

        withContext(CoroutineName("Child 2")) {
            delay(1000)
            log("Hello 2")
        }

        log("After")
    }

// [Parent] Before
// (1 sec)
// [Child 1] Hello 1
// (1 sec)
// [Child 2] Hello 2
// [Parent] After

supervisorScope

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fun main() =
    runBlocking {
        println("Before")

        supervisorScope {
            launch {
                delay(1000)
                throw Error()
            }

            launch {
                delay(2000)
                println("Done")
            }
        }

        println("After")
    }

// Before
// (1 sec)
// Exception...
// (1 sec)
// Done
// After
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
fun main() =
    runBlocking {
        println("Before")

        withContext(SupervisorJob()) {
            launch {
                delay(1000)
                throw Error()
            }

            launch {
                delay(2000)
                println("Done")
            }
        }

        println("After")
    }

// Before
// (1 sec)
// Exception...

withTimeout

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private suspend fun test(): Int =
    withTimeout(Duration.ofMillis(1500)) {
        delay(Duration.ofMillis(1000))
        println("Still thinking")
        delay(Duration.ofMillis(1000))
        println("Done!")
        42
    }

suspend fun main(): Unit =
    coroutineScope {
        try {
            test()
        } catch (e: TimeoutCancellationException) {
            println("Cancelled")
        }
        delay(Duration.ofMillis(1000)) // Extra timeout does not help,
        // `test` body was cancelled
    }

// (1 sec)
// Still thinking
// (0.5 sec)
// Cancelled

코루틴 스코프 함수 연결하기

추가적인 연산

요약