等待任务等于在ContinueWith中抛出错误任务的异常



以下内容不是多余的吗?

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'

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

  • 忽略取消结果;即使CopyToBlobAsync返回的Task被取消,ContinueWith返回的Task也会成功完成。这可能是故意的行为。
  • 忽略成功的结果;从CopyToBlobAsync返回的任何值都被丢弃。
  • 它通过直接抛出t.Exception将任何异常包装在AggregateException中。这几乎肯定是错误行为。

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

您可以在某些情况下使用ContinueWith而不是await来执行任务。在我的代码中,我通常只在延续很简单的情况下才这样做,我不需要延续中的上下文,也不想要async状态机的开销。在大多数情况下,您应该选择await可能与ConfigureAwait(false)结合使用。

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

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

最新更新