簡體   English   中英

在協程范圍內引發異常時,協程范圍可重用嗎?

[英]When you throw an exception in a coroutine scope, is the coroutine scope reusable?

我一直在用協程找出錯誤處理方面的問題,我已經按照以下步驟縮小了單元測試的范圍:

  1. 我用任何調度程序創建一個協程作用域。
  2. 我在異步塊(甚至嵌套的異步塊)中在此范圍內的任何地方拋出異常。
  3. 我對返回的延遲值調用await並處理異常。
  4. 一切都很好。 但是,當我嘗試使用相同的協程范圍來啟動新的協程時,總是會例外地完成,但有相同的例外。

    這是測試:

     fun `when you throw an exception in a coroutine scope, is the coroutine scope dead?`() { val parentJob = Job() val coroutineScope = CoroutineScope(parentJob + Dispatchers.Default) val deferredResult = coroutineScope.async { throw IllegalStateException() } runBlocking { try { deferredResult.await() } catch (e: IllegalStateException) { println("We caught the exception. Good.") } try { coroutineScope.async { println("we can still use the scope") }.await() } catch (e: IllegalStateException) { println("Why is this same exception still being thrown?") } } } 

這是測試的輸出:

We caught the exception. Good.
Why is this same exception still being thrown?
  • 為什么會這樣呢?

    • 我的理解是,您可以正常處理異常並使用協程從異常中恢復。
  • 我應該如何處理例外情況?

    • 我需要創建一個新的coroutineScope嗎?
    • 如果我想繼續使用相同的coroutineScope,是否可以永遠不會拋出異常?
    • 我應該返回Either<Result, Exception>嗎?
    • 我已經嘗試過使用CoroutineExceptionHandler,但仍然得到相同的結果。

注意我正在使用Kotlin 1.3

當您在范圍內啟動協程(使用asynclaunch )時,默認情況下協程失敗會取消此范圍以立即取消所有其他子級。 這種設計避免了晃動和丟失異常。

這里的一般建議是:

  • 除非確實需要並發,否則不要使用async / await 當使用暫停函數設計代碼時,不需要使用asyncawait

  • 如果確實需要並發執行,請遵循以下模式:

     coroutineScope { val d1 = async { doOne() } val d2 = async { doTwo() } ... // retrieve and process results process(d1.await(), d2.await(), .... ) } 

如果您需要處理並發操作的失敗,則在coroutineScope { ... }周圍try { ... } catch { ... } ,以捕獲任何並發執行的操作中的失敗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM