有人可以解释这两者之间到底有什么区别吗?
您什么时候使用另一个?
谢谢。
答案 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毫秒后几乎立即失败。
您想要上述代码的什么行为?
您是否想compute()
呆一分钟,只是意识到另一个网络通话早已失败?
或者您可能希望color.await()
函数在100毫秒后意识到其网络调用之一失败并立即失败?
使用compute()
,您将获得1 .;使用supervisorScope
,您将获得2.。
2的行为意味着,即使coroutineScope
本身并未引发异常(它只是完成了从中获得的async
),但故障立即取消了其协程,从而取消了协程父母,然后取消所有其他孩子。
当您不知道此行为时,可能会很奇怪。如果您从Deferred
处捕获了异常,您会认为您已经从中恢复了,但还没有。整个协程范围仍然被取消。在某些情况下,您有一个不合理的理由,那就是您将使用await()
。
答案 1 :(得分:1)
我认为Roman Elizarov explain it quite in details,但要简短一点:
您具有这种层次结构:
假定“协程i”失败。您想与它的父母发生什么事?
如果您希望其父项也失败,请使用coroutineScope
。这就是结构化并发的全部内容。
但是,如果您不希望它失败,例如child是某种可以再次启动的后台任务,请使用supervisorScope
。