何时使用coroutineScope与SupervisorScope?

时间:2018-12-02 06:15:24

标签: kotlin kotlin-coroutines

有人可以解释这两者之间到底有什么区别吗?

您什么时候使用另一个?

谢谢。

2 个答案:

答案 0 :(得分:6)

解释差异的最好方法是解释 public ActionResult DownloadExcel() { System.Data.DataTable result = Helpers.TaxMailingExcelBuilder.Export(); Response.Clear(); Response.Buffer = true; Response.AddHeader("content-disposition", "attachment;filename=myData.csv"); Response.Charset = ""; Response.ContentType = @"application/text"; Response.Output.Write(ExportDataTable(result).ToString()); Response.Flush(); Response.End(); return View(); } private StringBuilder ExportDataTable(System.Data.DataTable dt) { var stringBuilder = new StringBuilder(); for (int i = 0; i < dt.Rows.Count; i++) { for (int j = 0; j < dt.Columns.Count; j++) { stringBuilder.Append(dt.Rows[i][j].ToString() + ','); } stringBuilder.Append("rn"); } return stringBuilder; } } 的机制。考虑以下代码:

coroutineScope

suspend fun main() = println(compute()) suspend fun compute(): String = coroutineScope { val color = async { delay(60_000); "purple" } val height = async<Double> { delay(100); throw HttpException() } "A %s box %.1f inches tall".format(color.await(), height.await()) } 从网络中获取两件事,并将它们组合成一个字符串描述。在这种情况下,第一次获取会花费很长时间,但最终会成功;第二个在100毫秒后几乎立即失败。

您想要上述代码的什么行为?

  1. 您是否想compute()呆一分钟,只是意识到另一个网络通话早已失败?

  2. 或者您可能希望color.await()函数在100毫秒后意识到其网络调用之一失败并立即失败?

使用compute(),您将获得1 .;使用supervisorScope,您将获得2.。

2的行为意味着,即使coroutineScope本身并未引发异常(它只是完成了从中获得的async),但故障立即取消了其协程,从而取消了协程父母,然后取消所有其他孩子。

当您不知道此行为时,可能会很奇怪。如果您从Deferred处捕获了异常,您会认为您已经从中恢复了,但还没有。整个协程范围仍然被取消。在某些情况下,您有一个不合理的理由,那就是您将使用await()

答案 1 :(得分:1)

我认为Roman Elizarov explain it quite in details,但要简短一点:

您具有这种层次结构:

  • 亲子协程
    • 儿童协程1
    • 儿童协程2
    • ...
    • 儿童协程N

假定“协程i”失败。您想与它的父母发生什么事?

如果您希望其父项也失败,请使用coroutineScope。这就是结构化并发的全部内容。

但是,如果您不希望它失败,例如child是某种可以再次启动的后台任务,请使用supervisorScope