重新使用 HttpClient 但每个请求的超时设置不同?
Posted
技术标签:
【中文标题】重新使用 HttpClient 但每个请求的超时设置不同?【英文标题】:Re-using HttpClient but with a different Timeout setting per request? 【发布时间】:2017-10-22 13:36:03 【问题描述】:为了重用与HttpClient
的开放 TCP 连接,您必须为所有请求共享一个实例。
这意味着我们不能简单地用不同的设置(例如超时或标头)实例化 HttpClient
。
我们如何共享连接并同时使用不同的设置?这很简单,实际上是默认设置,使用较旧的 HttpWebRequest
和 WebClient
基础架构。
请注意,在发出请求之前简单地设置 HttpClient.Timeout
不是线程安全的,并且在并发应用程序(例如 ASP.NET 网站)中不起作用。
【问题讨论】:
除了Timeout
,您希望在同一实例上更改哪些设置?诸如标头之类的东西可以根据请求进行设置,而不同的BaseAddress
并没有多大意义,因为每个不同的都需要一个新的连接。实际上,Timeout
可能是您希望在同一实例上更改的 only 属性。如果可以回答问题,我可以向您展示如何为每个请求使用不同的超时。
@ToddMenier 这是一个很好的观点。这将回答这个问题,是的!
需要澄清的是,重用HttpClient
意味着您正在重用一个单个 TCP 连接。这里不涉及“池化”。
@ToddMenier 我很确定这不是真的。这也意味着对同一个 HttpClient 对象的并行请求不会并行执行,我很确定也不是这种情况。
【参考方案1】:
在后台,HttpClient
只是使用取消令牌来实现超时行为。如果你想根据请求改变它,你可以直接做同样的事情:
using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(30));
await httpClient.GetAsync("http://www.google.com", cts.Token);
请注意,HttpClient
的默认超时时间为 100 秒,即使您在请求级别设置了更高的值,请求仍会在此时取消。要解决此问题,请在 HttpClient
上设置“最大”超时,该超时可以是无限的:
httpClient.Timeout = System.Threading.Timeout.InfiniteTimeSpan;
【讨论】:
在另一个答案中提到,这只能减少取消的时间。因此,如果您打算使用此方法,最好将默认超时设置为无限(或您可以满意的其他数量),并计划为每个 每个 请求。 @Todd Menier:我按照你的回答解决了类似的问题,但我无法解决,也许你可以帮助我:***.com/questions/54326681/…【参考方案2】:已接受的答案很好,但我想为将来寻找此问题的任何人提供另一种方案。就我而言,我已经在使用 CancellationTokenSource,当用户选择取消时,它会取消其令牌。因此,在这种情况下,您仍然可以通过使用 CancellationTokenSource 的 CreateLinkedTokenSource 方法来使用此技术。因此,在我的场景中,http 操作将因超时或用户干预而取消。这是一个示例:
public async static Task<HttpResponseMessage> SendRequest(CancellationToken cancellationToken)
var ctsForTimeout = new CancellationTokenSource();
ctsForTimeout.CancelAfter(TimeSpan.FromSeconds(5));
var cancellationTokenForTimeout = ctsForTimeout.Token;
using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cancellationTokenForTimeout))
try
return await httpClient.GetAsync("http://asdfadsf", linkedCts.Token);
catch
//just for illustration purposes
if (cancellationTokenForTimeout.IsCancellationRequested)
Console.WriteLine("timeout");
else if (cancellationToken.IsCancellationRequested)
Console.WriteLine("other cancellation token cancelled");
throw;
【讨论】:
以上是关于重新使用 HttpClient 但每个请求的超时设置不同?的主要内容,如果未能解决你的问题,请参考以下文章
android 用httpclient登录无法保持会话状态 最后两次请求的cookie都不一样!我明明设成一样了?
C# 中的 httpClient 调用超时,而 cUrl 正在工作
Httpclient在.net core3.1上成功运行,但更新到.net 5中连接超时(System.Net.Sockets.SocketException (10060)) C#