【问题标题】:HttpClient PostAsync is blockingHttpClient PostAsync 被阻塞
【发布时间】:2019-06-25 02:03:21
【问题描述】:

我正在尝试从我的 UI 线程调用 HttpClient.PostAsync()。我已经在我的开发机器上对此进行了测试,它工作正常,但在我的目标机器上似乎阻塞了 UI 线程。我在两台机器上都运行了这个测试

int tick = Environment.TickCount;
Task<HttpResponseMessage> postTask = _httpClient.PostAsync(Uri,
    new StringContent(messageString));
MessageBox.Show(String.Format("Time {0}", Environment.TickCount - tick));
response = await postTask;

在我的开发机器上,消息框显示 ~

【问题讨论】:

  • 您必须对阻塞代码调用的所有方法的传递闭包中的每个等待使用 ConfigureAwait(false),包括所有第三方和第二方代码。使用 ConfigureAwait(false) 避免死锁
  • @bolkay,他们从帖子中获取任务,然后等待。
  • 我相信PostAsync 的一部分必须运行才能发布其延续并收回控制权。从记忆中我认为它必须获取代理服务器信息(在您的目标机器上可能不同)并在它产生之前解析 DNS。至少对于第一次通话。对于后续调用,它应该被缓存。您是否反复看到相同的结果?
  • @JohnWu 在应用程序启动后似乎延迟了第一个请求。我没有注意到后续请求有任何延迟,但它们也发生得非常快,所以我不能说下面的请求是否仍然阻塞,或者它们发生的速度是否足够快以至于没有注意到。我知道的一件事是第一次交互必须进行身份验证。这是直接连接到局域网的Http服务器,Uri是静态IP地址

标签: c# async-await dotnet-httpclient


【解决方案1】:

这可能是 DNS 查找的问题,并且正如 cmets 中所指出的,如果您绝对需要它来阻止 UI,则可能会缓存以供将来调用。

解决这个问题的唯一方法是卸载它(以线程池线程为代价)..

var postTask = await Task.Run(() => _httpClient.PostAsync(Uri, new StringContent(messageString)));

【讨论】:

    【解决方案2】:

    为了将来参考,我想我找到了解决方案。看起来时间被花在了ServicePointManager.FindServicePoint() 上,这被称为创建WebRequest。我注意到用适当的网关配置我的目标机器解决了速度问题,但是在我的情况下,机器并不总是连接到更大的 LAN 或互联网,所以我想知道如果你将 HttpClientHandler.UseProxies 设置为 false 它会跳过尝试找到一个代理服务器,它现在会在大约 32 毫秒内返回。

    奇怪的是他们没有FindServicePoint() async 但这似乎是问题所在。我以为我的 Uri 是一个固定的 ip,即http://192.168.250.1:80/...,我会绕过所有这些东西,但事实并非如此

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多