HttpClient 如何处理超时?

12
有两个超时属性可以在HttpClient上设置:HttpClient.TimeOutWebRequestHandler.ReadWriteTimeout
第一个仅是请求/响应的超时,如果下载/上传时间超过它,那么传输将被中断,不会有任何问题。这可以通过将超时设置为无限来覆盖,但我不确定这样做会有什么后果。
现在,后者(ReadWriteTimeOut)-至少在我理解的范围内-应该向下传播到NetworkStream,在那里它影响请求/响应流可以阻塞(空闲)多长时间,直到超时。
HttpClient正在使用HttpWebRequest方法的异步版本,但正如此处所述:

在异步请求的情况下,客户端应用程序负责实现自己的超时机制。

根本没有解释他们想要什么样的超时机制(网络流空闲超时?整个HTTP GET的超时?等等...),这让我感到非常困惑。
因此,我的问题是,HttpClient如何处理网络/协议超时?我想使用HttpClient上传/下载潜在的大文件,所以我将HttpClient.TimeOut设置为无限。但我担心这样做会使应用程序面临等待服务器/网络拒绝完成某些事件的风险。

你有关于这些超时的更多细节吗? - Sandeep Kumar
@SandeepKumar 除了我在下面“Leo Y”的回答中的评论外,我没有得到更多细节。对于我来说,要反编译和查看的层次太多了。我建议使用试错法来测试您感兴趣的超时情况。 - Paya
1
@SandeepKumar 将 WebRequestHandler 的一个实例传递给 HttpClient 的构造函数。在那之前,请将 WebRequestHandlerReadWriteTimeout 属性设置为您想要的任何值。这篇文章 可能会帮助解释一些东西。 - Paya
谢谢,我学到了新东西 :) - Sandeep Kumar
1
@AntonyThomas,你知道我在我的评论中从2015年11月7日起就已经链接到了那篇文章吗?它就在你的上面两个评论处。 - Paya
显示剩余3条评论
2个回答

1
当使用HttpClient下载文件时,有两个选项:
  1. 在Get请求中使用HttpCompletionOption.ResponseContentRead(这是默认的隐式选项)。然后HttpClient.Timeout将有效地应用于整个下载过程。我想这就是你考虑无限超时的情况。

  2. 在Get请求中明确使用HttpCompletionOption.ResponseHeadersRead。那么HttpClient.Timeout仅适用于获取没有内容的Head响应。之后,您可以通过response.Content.ReadAsStreamAsync()等方式自行管理超时来下载内容。

我想选项2是您正在寻求的。只需设置HttpClient.Timeout以在合理的时间内从服务器获取响应,然后下载内容即可。

0

你的引用是针对 HttpWebRequest 的。然而,HttpClient.Timeout(仅在 .NET 4.5 中有效)是针对 HttpClient 的。因此,它处理使用 HttpClient API 时的超时。但是,将其设置为无限是一种不好的做法。在这种情况下,使用内部超时,将在约10分钟后抛出异常(如果在 .NET 4.5 中未更改内部超时值)。


正如我所说,HttpClient只是HttpWebRequest的包装器,因此引用是相关的。你能详细说明一下那些“内部超时”吗?我觉得你的陈述相当模糊,因为我的原始问题实际上是关于内部细节的细节。此外,将.Timeout设置为无限后,我甚至可以轻松地保持连接打开时间比20分钟长得多。 - Paya
HttpClient不是一个包装器,因为它与特定URL无关,相反HttpWebRequest绑定到特定URL。如果在服务器端实现了特定的行为,可以保持连接打开。例如,SSE(服务器发送事件)协议就利用了这一点。 单个调用(例如调用HttpClient.GetStringAsync())利用了HttpWebRequest异步方法进行实现,正如您所提到的。我将检查HttpClient.Timeout的确切用法,并将在答案中更新此信息。 - Leo Y
1
它是一个包装器,因为它只是将所有HTTP协议处理委托给HttpWebRequest。你可以在多个URL上使用它这一事实是无关紧要的。HttpClient.Timeout几乎是无用的,因为它只是通过在请求开始时设置定时器来工作,如果整个异步操作(请求+响应)没有及时完成,它就会被取消。任何人都可以在最抽象的层次上使用CancellationTokenSource + Task.Delay实现这一点,因此它是无用的属性。问题是关于你提到的内部超时 - Paya
事实上,它被用作取消令牌的超时时间。现在,既然已经说了以上所有内容,你已经得到了关于“HttpClient如何处理超时”的答案。 - Leo Y
那又怎么与我自己相矛盾了呢?我通过上传200 MB文件并将Thread.Sleep(1000)放入自定义流类中来将上传速度降至最低。 - Paya
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接