[英]Why CoroutineExceptionHandler didn't catch/handle my exception?
[英]Propagate exception from async to CoroutineExceptionHandler
我有一個async
協程,可能會引發異常。 如何將異常傳播到我的CoroutineExceptionHandler
? 使用try/catch
await
我能夠捕獲異常,但無論上下文如何,我似乎都無法將處理傳播到處理程序:
val handler = CoroutineExceptionHandler { _, e -> e.printStackTrace() }
val context = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + handler
val scope = CoroutineScope(context)
val async = scope.async {
throw Exception("Test exception")
}
runBlocking {
try {
async.await()
} catch (e: Exception) {
log.error("Exception thrown", e)
}
delay(1_000)
}
我嘗試從 catch 中重新拋出異常,或者用以下一些結構包裝它:
catch (e: Exception) {
throw e
// withContext(context) { throw e }
// scope.launch { throw e }
// supervisorScope { throw e }
}
可悲的是,他們都沒有將其傳播給處理程序。 我可以以某種方式將CoroutineExceptionHandler
與async
協程一起使用嗎?
有幾種方法可以使它工作。 首先,正如異步文檔中所述,它會在失敗時取消父作業。 這就是為什么scope.launch { throw e }
什么都不做,到那時 scope 被取消了,協程甚至沒有啟動。
然后,正如受監督協程文檔中所述,要在受監督的上下文中處理未捕獲的異常,您應該將處理程序安裝到孩子的上下文中。 因此,例如以下代碼會將異常傳遞給您的處理程序
runBlocking {
supervisorScope {
launch(handler){
async.await()
}
}
}
go 的另一種方法是將異常處理程序安裝到協程的根 scope 中,例如像這樣
runBlocking {
GlobalScope.launch(handler) {
async.await()
}.join()
}
這里我使用GlobalScope
進行演示,但它可以是任何活動的(未取消的)scope。
協程異常處理文檔中有許多示例,我建議您也檢查並運行它們。
不,你不能。
async
返回一個 Deferred,就像一個未來。 異常處理程序不適用,因為如果有異常,它就是 Deferred 的返回值。
從文檔:
除此之外,async builder 總是捕獲所有異常並在生成的 Deferred object 中表示它們,因此它的 CoroutineExceptionHandler 也不起作用。
來源: https://kotlinlang.org/docs/exception-handling.html#coroutineexceptionhandler
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.