【问题标题】:Set c# HttpClient request timeout regardless the host/server is available or not无论主机/服务器是否可用,都设置 c# HttpClient 请求超时
【发布时间】:2020-03-10 02:28:43
【问题描述】:

我正面临着 httpclient 和超时配置。在做了很多谷歌搜索后,我得出了以下结论:

  • 只有当我连接到可用的主机/服务器时,Http 客户端超时才正常。
  • 如果主机不可用或服务器关闭,HttpClient.Timeout 无关紧要,大约 80 秒后我会收到一个包含 SocketException(连接被拒绝)的 TaskCancelledException。

我知道 httpClient 超时仅在服务器收到请求后才起作用,因此,如果主机/服务器关闭,我会得到与套接字相关的很长时间的超时。

我需要为我的 httpClient getAsync、postAsync... 请求配置更“宽”的超时,并在指定的时间停止操作,无论服务器是否可用。

我无法弄清楚我可以做些什么来有效地控制时间,stackoverflow 线程 (link) 建议以这种方式执行任务调用方法:

var timeout = Task.Delay(10000); // 10 seconds timeout
var request = httpClient.GetAsync("http://www.google.com");

await Task.WhenAny(timeout, request); // wait for either timeout or the request

if (timeout.IsCompleted) // if the timeout ended first, then handle it
{
    // handle timeout
}

// otherwise continue processing the request result
var response = await request;

虽然这可能有效,但我会丢失套接字异常并提供较差的控制。因为,简而言之,我想做的是找到一种方法来设置解决/连接到服务器的超时时间(大约 2 秒),以及在与服务器建立连接后等待响应的更高超时时间。

这对我来说很有意义,因为我的 Web 服务器是通过本地网络访问的,因此,2 秒足以得出“服务器不可用”的结论,但是一旦服务器开始处理响应,我需要更大的超时时间等待响应。

提前致谢。

【问题讨论】:

    标签: c# timeout dotnet-httpclient


    【解决方案1】:

    我正在考虑这种解决方法:

    启动两个并行 http 请求,其中一个是虚拟 get 请求(服务器直接响应 OK),我将使用您在问题中看到的推荐方法等待此任务 2 秒。另一个请求是“真正的请求”......如果第一个请求没有在两秒钟内完成,我也会取消第二个请求,但如果第一个请求结束正常,那么服务器工作正常,我依靠 httpClient.Timeout第二个请求。

    是的,这是服务器的开销,因为每个请求都变成了两个请求,但是我的服务器是本地网络,不超过 5-10 个客户端每分钟只执行 1-2 个请求,所以,我会考虑这种方法。或者它可能是个坏主意……你怎么看?

    【讨论】:

      【解决方案2】:

      那个stackoverflow线程...,建议任务调用方法

      链接问题方法是正确的方法。

      基本上,问题在于连接超时由操作系统设置管理,您无法直接在代码中进行设置。

      虽然这可能有效,但我会丢失套接字异常并提供较差的控制

      捕获和记录套接字异常(或任何其他异常)没有问题。只需为“主要”任务设置适当的任务取消:

      // task is returned from async method performing payload, e.g. httpClient.GetAsync
      task.ContinueWith(
          t =>
          {
              var exception = t.Exception;
      
              // do what you want here
          },
          TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
      

      【讨论】:

      • 我会试一试,但是,事先,我认为这与我的目标无关,也就是说,正如问题中所述:“......简而言之,我正在尝试要做的是找到一种方法来设置解析/连接到服务器的超时时间(大约 2 秒),并在与服务器的连接建立后等待响应的更高超时时间。”
      • @FranCD:是的,你不能设置它。因此,唯一的方法是“忘记”长时间运行的连接尝试。
      • 真的很烦人,它应该存在一种方法来正确控制不同的超时,因为 2 秒足以确定服务器是否可用,但对于等待某些请求结果来说可能太少了。我发布了一个带有解决方法想法的答案(我今天会尝试)¿你觉得这个想法怎么样?
      【解决方案3】:

      既然GetAsync返回Task那么你就可以使用Task.Wait Method

      例如:

      var readTask = httpClient.GetAsync("http://www.google.com");
      
      if (readTask.Wait(2 * 1000))
      {
          // Return Result if exec dosn't take more than 2 sec
          // return await readTask;
          return readTask.Result;
      }
      else
      {
          // Fail to complete exec in 2 sec
          return string.Empty;
      }
      

      【讨论】:

      • 我会试一试,但是,事先,我认为这与我的目标无关,即,如问题所述:“......简而言之,我正在尝试要做的是找到一种方法来设置解析/连接到服务器的超时时间(大约 2 秒),并在与服务器建立连接后等待响应的更高超时时间。”
      • @FranCD:不要以这种方式等待异步任务。此代码 1) 阻塞调用线程; 2)导致死锁。以异步方式执行,例如您链接的问题。
      • 我只是在这里解释等待方法,我参考 MSDN 链接知道它的工作原理。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-17
      • 2019-10-14
      • 2017-07-12
      • 1970-01-01
      • 1970-01-01
      • 2020-02-11
      • 2020-03-13
      相关资源
      最近更新 更多