【问题标题】:Await on HttpClient.GetStreamAsync Awaits Forever [closed]等待 HttpClient.GetStreamAsync 永远等待[关闭]
【发布时间】:2021-02-15 13:01:44
【问题描述】:

问题是,当我将await 放在HttpClient.GetStreamAsync() 之前时,它不会返回任何内容,Visual Studio 会自行挂起,只要我决定停止调试,就不会返回任何内容。当我尝试使用.GetAwaiter().GetResult() 时,它会提示我在this 问题上显示的错误,不幸的是没有产生任何解决方案。 这些错误会导致什么结果? TLS 问题是不确定的。网络团队确保我试图从中获取结果的 api 的地雷请求没有被阻止,并且对方确认他们也没有阻止我们的请求。可以确认这一点,因为 Postman 请求与 api 配合得很好。我使用了HttpClientWebRequest 提示同样的错误。等待甚至不会导致错误,它只是闲置......

为什么我会遇到这个问题?我怎样才能克服它?任何帮助表示赞赏。

(我尝试过的代码和solutions可以在this我的问题中找到。

【问题讨论】:

  • 所有错误都指向服务器的问题。您无法在客户端解决此问题。您只能为您的操作添加超时,这样您就不会永远等待。顺便说一句,阻止异步操作是个坏主意。通过允许过时的算法来削弱 TLS 加密也是如此
  • @PanagiotisKanavos,我创建了一个工作正常的 .Net Framework 4.7.2 项目和一个 .Net Core 3.1 项目。一点都不麻烦。但是在 .Net Framework 4.7.2 上运行的项目不知何故无法按预期工作。此问题不可能是服务器问题。
  • 创建一个新的 HttpClient 实例也很糟糕,这个类是线程安全的并且意味着可以重用。否则,您最终会耗尽所有可用的套接字,而这可能会导致问题。检查You're using HttpClient wrong and its destabilizing your software
  • 您没有提供足够的信息,所以人们只能猜测出了什么问题。特别是在 this 问题中。 HttpClient 没有损坏。如果有流,GetStreamAsync 会打开它。所以要么服务器被阻塞,要么客户端代码以某种方式最终阻塞了自己。 HttpClient 没有损坏。您在原始问题中发布的代码虽然有严重的错误 - 阻止异步调用、削弱安全性、创建新的 HttpClient 实例并可能耗尽可用的套接字
  • 我想Postman 可以使用您的公司代理设置,而.Net 应用程序可能会尝试直接建立它。看起来像是您的环境有问题,而不是代码。

标签: c# .net async-await dotnet-httpclient


【解决方案1】:

对您的问题的简短回答是“您的服务器没有返回所有数据,并且您确实要求方法等待”。但这没有帮助。

您可能希望 HttpClient 获取异步方法超时。下面的代码是如何做到这一点的人为示例。下面是代码的作用:

  1. 创建了一个 CancellationToken 源,它将在 500 毫秒后发出 CancellationToken 已取消的信号。
  2. 我获得了 Google 搜索页面的默认登录页面。我只使用 Geta 同步而不是 GetstreamAsync,因为我想不出我不必自己编写代码的流响应的来源。虽然是同一个校长。在我的网络上,500 毫秒的超时时间已经足够了,所以我收到一条消息“响应代码 = OK”。
  3. 如果我将 500 毫秒更改为 10 毫秒,响应不会在时间用完之前完成,我会收到“任务已取消”的消息。

所以,当您说“等待”时,它的真正意思是“在这里等到我调用的方法完成,除非我在此之前取消等待。另外请记住,根据您的需要,可能有各种 CancellationTokenSources。这只是一个例子。

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace cancel
{
    class Program
    {
        static async Task Main(string[] args)
        {
            CancellationTokenSource cancellationSource = new CancellationTokenSource(new TimeSpan(0,0,0,0,5000)); //Succeeds
            //CancellationTokenSource cancellationSource = new CancellationTokenSource(new TimeSpan(0,0,0,0,10)); //Fails
            CancellationToken cancellationToken = cancellationSource.Token;

            var client = new HttpClient();
            try
            {
                var result = await client.GetAsync("https://www.google.com",cancellationToken);
                Console.WriteLine($"Response code = {result.StatusCode}");
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }
    }
}

【讨论】:

  • 感谢您对限制等待时间的建议。这肯定会对我有很大帮助。您是否知道 .Net Framework 4.7.2 Web API 项目如何无法使用HttpClient 获取某些内容,但在使用相同网络的同一台机器上,.Net Core 3.1 控制台应用程序获取相同的内容查询就好了?此外,常规的 .Net Framework 4.7.2 控制台应用程序与 .Net Core 3.1 一样好。在Web API项目上继承的ApiController会导致这个问题吗?
  • 我需要更多信息,但我可以告诉您,.Net Framework HttpClient 的工作方式和 .NET Core HttpClient 的工作方式几乎没有区别。如果我不得不猜测,我会说 4.7.2 代码中存在错误。
  • 我会和网络团队谈谈,看看网络是否会导致任何错误。他们说他们修复了它,因为我使用来自同一个查询的其他项目/工具得到了好的结果,他们只是说这与网络无关:/我希望他们错了,因为我对代码的可能方式一无所知有错误或错误。感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 2013-11-24
  • 2012-02-24
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多