栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用await / async时,HttpClient.GetAsync(...)从不返回

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用await / async时,HttpClient.GetAsync(...)从不返回

您正在滥用API。

情况就是这样:在ASP.NET中,一次只有一个线程可以处理一个请求。如果有必要,您可以执行一些并行处理(从线程池中借用其他线程),但是只有一个线程具有请求上下文(其他线程没有请求上下文)。

这由ASP.NET管理

SynchronizationContext

默认情况下,当您使用

await
a时
Task
,该方法将在捕获到的对象
SynchronizationContext
(或没有捕获
TaskScheduler
到的对象
SynchronizationContext
)上继续。通常,这就是您想要的:异步控制器操作将执行
await
某些操作,并且在恢复操作时,将在请求上下文中恢复操作。

因此,这就是

test5
失败的原因:

  • Test5Controller.Get
    执行
    AsyncAwait_GetSomeDataAsync
    (在ASP.NET请求上下文中)。
  • AsyncAwait_GetSomeDataAsync
    执行
    HttpClient.GetAsync
    (在ASP.NET请求上下文中)。
  • HTTP请求被发送出去,并
    HttpClient.GetAsync
    返回一个uncompleted
    Task
  • AsyncAwait_GetSomeDataAsync
    等待
    Task
    ; 由于未完成,因此
    AsyncAwait_GetSomeDataAsync
    返回uncompleted
    Task
  • Test5Controller.Get
    阻塞 当前线程,直到
    Task
    完成为止。
  • HTTP响应进入,
    Task
    并由返回
    HttpClient.GetAsync
    完成。
  • AsyncAwait_GetSomeDataAsync
    尝试在ASP.NET请求上下文中恢复。但是,在该上下文中已经有一个线程:该线程在中被阻塞
    Test5Controller.Get
  • 僵局。

这就是其他方法起作用的原因:

  • test1
    test2
    test3
    ):在ASP.NET请求上下文 之外
    Continuations_GetSomeDataAsync
    调度到线程池的继续。这使得返回者可以完成而不必重新输入请求上下文。 __
    Task``Continuations_GetSomeDataAsync
  • test4
    test6
    ):由于
    Task
    正在 等待 ,因此不会阻止ASP.NET请求线程。
    AsyncAwait_GetSomeDataAsync
    当准备好继续时,这允许使用ASP.NET请求上下文。

这是最佳做法:

  1. 在您的“库”
    async
    方法中,请
    ConfigureAwait(false)
    尽可能使用。在你的情况,这将改变
    AsyncAwait_GetSomeDataAsync
    var result = await httpClient.GetAsync("http://stackoverflow.com", HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
  2. 不要阻塞
    Task
    s;它是
    async
    一路下滑。换句话说,请使用
    await
    代替
    GetResult
    Task.Result
    并且
    Task.Wait
    也应替换为
    await
    )。

这样,您将获得两个好处:延续(

AsyncAwait_GetSomeDataAsync
方法的其余部分)在基本线程池线程上运行,该线程不必输入ASP.NET请求上下文;控制器本身是
async
(不会阻塞请求线程)。

更多信息:

  • 我的
    async
    /
    await
    介绍性帖子,其中简要介绍了
    Task
    侍者的使用方式
    SynchronizationContext
  • 在异步/等待FAQ,其中进入的背景下更详细。另请参见等待,UI和死锁!天啊!即使您使用的是ASP.NET而不是UI,这 适用于此,因为ASP.NET一次
    SynchronizationContext
    将请求上下文限制为仅一个线程。
  • 此MSDN论坛帖子。
  • Stephen Toub 演示了此死锁(使用UI),Lucian Wischik也进行了演示。

2012年7月13日更新: 将此答案纳入博客文章中。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/447191.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号