异步方法中的 Await vs Task.Result [重复]

Posted

技术标签:

【中文标题】异步方法中的 Await vs Task.Result [重复]【英文标题】:Await vs Task.Result in an Async Method [duplicate] 【发布时间】:2015-11-21 06:17:59 【问题描述】:

执行以下操作有什么区别:

async Task<T> method()
    var r = await dynamodb.GetItemAsync(...)
    return r.Item;

async Task<T> method()
    var task = dynamodb.GetItemAsync(...)
    return task.Result.Item;

就我而言,出于某种原因,只有第二个有效。第一个似乎永远不会结束。

【问题讨论】:

所以我发现 await 可能挂起的唯一原因是来自下面的 SO 答案。我想我会在这里发表评论以帮助未来的我。 ***.com/questions/13489065/…***.com/questions/9895048/… 试试 await dynamodb.GetItemAsync(...).ConfigureAwait(false) 【参考方案1】:

task.Result 正在访问属性的 get 访问器阻塞调用线程,直到异步操作完成;相当于调用Wait method。 一旦操作的结果可用,它就会被存储并在后续调用 Result 属性时立即返回。请注意,如果在任务运行过程中发生异常,或者如果任务已被取消,则 Result 属性不会返回值。相反,尝试访问属性值会引发 AggregateException 异常。 唯一的区别是 await 不会阻塞。相反,它将异步等待任务完成然后恢复

【讨论】:

为什么在这种情况下等待不起作用,但结果确实起作用 调用Result bare 是一个隐藏的死锁。 捎带 Joshua,你可以在这里找到更多关于它为什么会导致隐藏死锁的信息:***.com/questions/17248680/…【参考方案2】:

await 异步解包任务的结果,而仅使用 Result 会阻塞,直到任务完成。

See this explanantion from Jon Skeet.

【讨论】:

为什么在这种情况下等待不起作用,但结果确实起作用 @luis:缺少任何其他信息,我看到的唯一答案是它实际上不适用于await 案例。你只是错误地认为它确实是因为方法本身返回。但是正在等待的任务可能不会以任何方式完成。如果您想要 that 的答案(这与您提出的问题不同),您需要发布一个新问题,清楚地说明这一点,并提供可靠地重现问题的 a good, minimal, complete code example。 调用Result bare 是一个隐藏的死锁。 这篇文章有点老了,但你做了await Method() 吗? @user2953241: .Result 或其所有可能的变体导致线程池线程等待线程池上的作业完成。这可能会耗尽线程池上的所有线程,而没有一个线程可以执行实际工作。

以上是关于异步方法中的 Await vs Task.Result [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Async 和 Await 的异步编程 资料汇总

Async/Await 同步方法中的异步和异步方法中的异步

异步 callback vs promise vs async/await

异步编程Async/await关键字

C#:异步编程中的 async 和 await

如何正确理解.NET 4.5和C#5.0中的async/await异步编程模式