等待任务等于在ContinueWith中抛出故障任务的异常

时间:2013-04-22 08:51:18

标签: c# async-await

以下不是多余的?

await blob.CopyToBlobAsync(newBlob).
       ContinueWith((t) => { if (t.IsFaulted) throw t.Exception; });

好像没有ContinueWith调用,会直接抛出异常吗?

何时使用continueWith而不是等待任务?

以下是相同的吗?

await myTask.ContinueWith(t => {'do something with the task t'});

await myTask;
'do something with the task MyTask'

1 个答案:

答案 0 :(得分:4)

ContinueWith(t => { if (t.IsFaulted) throw t.Exception; })行的语义与await任务直接CopyToBlobAsync的语义不同:

  • 忽略取消结果;即使Task返回的ContinueWith被取消,Task返回的CopyToBlobAsync也会成功完成。这可能是故意行为。
  • 它忽略了成功的结果; CopyToBlobAsync的任何返回值都将被删除。
  • 它通过直接抛出AggregateException来包装t.Exception中的任何例外。这几乎肯定是有缺陷的行为。

所以它不是完全多余的,并且可能是一个错误。

您可以在某些情况下使用ContinueWith而不是await任务。在我的代码中,我通常只在延续很简单的情况下执行此操作,我不需要继续中的上下文,并且我不希望async状态机的开销。在大多数情况下,您可能希望await可能与ConfigureAwait(false)结合使用。

你最后的例子不一样;默认情况下,ContinueWith将在线程池上执行,而默认情况下await将捕获上下文并在该上下文中执行延续。此外,您必须非常小心如何在延续中使用任务:您通常希望将异常和取消传播到延续任务,这并不像第一次出现那么容易。

简而言之,我几乎在每个场景中都推荐await。它更容易编写,更易于阅读,并且具有合理的默认行为。