coroutine job exception handling

참치돌고래·2022년 12월 2일
0

Exception handling

coroutineexception을 받게 되면, coroutine 스스로
parent를 취소하고, children에게 전파한다.

  1. children 에서 exception 발생
  2. parent로 전파, parent 취소
  3. parent의 child 전부 취소

stopping breaking exception

SupervisorJob

SupervisorJob은 child에서 expception 발생해도 cancel 되지 않는다.

fun main() : Unit = runBlocking {
    val scope = CoroutineScope(SupervisorJob())
    scope.launch {
        delay(1000)
        throw Error("some Error")
    }
    scope.launch {
        delay(2000)
        println("Will be printed")
    }
            delay(3000)
}

output

Exception : some error
Will be printed

SupervisorJob()의 경우에는 children이 여러개일 때,
children에서 exception이 발생해도 서로 영향을 주지 않는다는 이점이 있다.

supervisorScope

coroutine builders 를 supervisorScope로 래핑하는 방법이다.

fun main() : Unit = runBlocking {
    supervisorScope {
        launch {
            delay(1000)
            throw Error("some Error")
        }

        launch {
            delay(2000)
            println("Will be printed")
        }
    }
    delay(1000)
    println("Done")
}

suspending function 으로 래핑할 수 있다.

suspend fun notify(actions: List<UserAction>) =
	supervisorScope {
    	actions.forEach{ action -> 
        	launch {
            	notifyAnalytics(action)
            }
       }
 }

supervisorScopewithContext(supervisorJob()) 을 대체할 수 없다. withContextsupervisorJob을 부모로 할 뿐, context의 coroutine은 종료될 것이다.

await

class MyException : Throwable()

suspend fun main() = supervisorScope {
    val str1 = async<String> {
        delay(1000)
        throw MyException()
    }

    val str2 = async {
        delay(2000)
        "Text2"
    }

    try{
        println(str1.await())
    } catch (e : MyException) {
        println(e)
    }
    println(str2.await())
}

output

MyException
Text2

CancellationException does not propagate to its parent

만약 exception이 CancellationException의 하위타입이라면, 부모로 예외를 전파하지 않는다. 오직 해당 coroutine만 cancellation된다.
CancellationExceptionopen class이기 때문에, 확장가능하다.

object MyNonPropagatingException : CancellationException()

suspend fun main() : Unit = coroutineScope {
    launch {
        launch {
            delay(2000)
            println("Wibb not be printed")
        }
        throw MyNonPropagatingException
    }
    launch {
        delay(2000)
        print("Will be printed")
    }
}

output

Will be printed

Coroutine exception handler

SupervisorJob 과 exceptionHandler 를 추가한 coroutine을 생성.
exception이 발생해도 context에 있는 handler에 의해 error case 별 처리 가능하다.


fun main() : Unit = runBlocking {
    val handler =
        CoroutineExceptionHandler{ ctx, exception ->
            println("Caught $exception")
        }
    val scope = CoroutineScope(SupervisorJob() + handler)
    scope.launch {
        delay(1000)
        throw Error("some error")
    }
    scope.launch {
        delay(2000)
        println("Will be printed")
    }
    delay(3000)
}

output

Caught java.lang.Error: some error
Will be printed
profile
안녕하세요

0개의 댓글