访问异步调用的结果是否会使它同步?

时间:2019-07-03 06:07:18

标签: c# concurrency

我正在处理Http调用。

收到响应(HttpResponseMessage)后,我想以字符串形式访问其内容:

string responseContent = responseMessage.Content.ReadAsStringAsync().Result;

现在,ReadAsStringAsync()是异步的,但访问Result绝对应该是同步的。

我测试了代码,不确定以下内容:

  • 这将始终有效吗?,
  • 它为什么起作用?
  • 尝试访问Result时不会出现异常吗?

1 个答案:

答案 0 :(得分:2)

docs很容易回答这个问题:

  

访问属性的get访问器阻塞调用线程,直到异步操作完成;等效于调用Wait方法。

     

一旦操作结果可用,就将其存储并在随后对Result属性的调用中立即返回。请注意,如果在任务操作期间发生异常,或者任务已被取消,则Result属性不会返回值。相反,尝试访问属性值将引发AggregateException异常。

(强调我的)

直接回答您的问题;

  • 这将始终有效吗? -是的,在可能的情况下,除非任务失败或被取消。
  • 为什么起作用? -因为代码会在返回结果之前等待任务完成。
  • 尝试访问Result时是否会出现异常? -不,因为它不是简单的属性。根据文档的说明,如果任务失败或被取消,您可能会获得异常。

正如@Camilo Terevinto所指出的,根据您所使用的上下文,这可能并不总是如您所愿。可能会导致死锁。

原因是,如果在存在上下文(例如UI上下文,ASP.NET请求上下文等)的情况下使用它,则其调用.Wait()的内部机制可能导致死锁:正在等待将结果插入当前上下文的好时机,同时当前上下文正在阻塞以等待结果。您可能想看看Stephen Cleary's blog。您可以向下滚动到“导致死锁的原因”以了解更多信息。您也可以查看this question

当然,理想的解决方案是在整个链中一直使用async / await。