如何根据子协程抛出的异常类型取消SupervisorJob

How to cancel SupervisorJob based on the type of exception thrown by the child coroutine

我有一个负责启动一些子协程的主管

        supervisorScope {
               aListOfJobs.forEach { job -> launch(handler) { process(job) } }
            }
        }

其中处理程序是一些回调,用于处理子协程抛出的异常。

    val handler = CoroutineExceptionHandler { _, exception ->
        
       // for some exceptions I should allow the parent job to continue, and others I should not and trigger the cancellation of my parent
    }

似乎即使处理程序抛出异常(即我重新抛出接收到的异常),主管也没有被取消。

所以我的问题是,允许主管继续为某些异常而不是其他异常工作的惯用方法是什么?

您不能使用 CoroutineExceptionHandler 执行此操作,而应该使用 coroutineScopetry catch

try {
    coroutineScope {
        aListOfJobs.forEach { job ->
            launch {
                try {
                    process(job)
                } catch (e: WorkShouldСontinueExceprion) {
                }
            }
        }
    }
} catch (e: WorkShouldStopExceprion) {
}

如果回答:“允许主管继续为某些异常而不是其他异常工作的惯用方法是什么?”我同意@IR42。如果我们有许多不同类型的异常并且我们想忽略其中一些而在其他情况下失败,那么默认情况下失败并在特定情况下忽略可能更清楚。

但是,如果您的情况是通常忽略所有错误,但在一个或几个特定错误上失败(如显式“中止”异常),那么您可以手动调用 cancel()

supervisorScope {
    aListOfJobs.forEach { job ->
        launch {
            try {
                process(job)
            } catch (e: AbortException) {
                this@supervisorScope.cancel("message", e)
                throw e
            }
        }
    }
}