为了重用与HttpClient
的开放式TCP连接,您必须为所有请求共享一个实例。
这意味着我们无法使用不同的设置(例如超时或标头)简单地实例化HttpClient
。
我们如何共享连接并同时使用不同的设置?这很简单,实际上是默认设置,使用较早的HttpWebRequest
和WebClient
基础设施。
请注意,在发出请求之前简单地设置HttpClient.Timeout
不是线程安全的,并且不能在并发应用程序(例如ASP.NET网站)中工作。
答案 0 :(得分:32)
在幕后,HttpClient
只使用取消令牌来实现超时行为。如果您想根据请求改变它,可以直接执行相同操作:
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;
答案 1 :(得分:0)
可接受的答案很好,但是我想为将来寻求此解决方案的任何人提供另一个方案。就我而言,我已经在使用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;
}
}
}