.net 重复使用HttpClient,但每个请求的超时设置不同?

fcg9iug3  于 2023-05-02  发布在  .NET
关注(0)|答案(3)|浏览(125)

为了重用HttpClient的开放TCP连接,您必须为所有请求共享一个示例。
这意味着我们 * 不能 * 简单地用不同的设置示例化HttpClient(例如:例如超时或报头)。
我们如何共享连接并同时使用不同的设置?这非常容易,实际上是默认的,使用旧的HttpWebRequestWebClient基础设施。
请注意,在发出请求之前简单地设置HttpClient.Timeout不是线程安全的,并且在并发应用程序中不起作用(例如。例如ASP.NET网站)。

jgzswidk

jgzswidk1#

在后台,HttpClient只使用取消令牌来实现超时行为。如果您想根据请求改变它,可以直接执行相同的操作:

using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(30));
await httpClient.GetAsync("http://www.google.com", cts.Token);

请注意,HttpClient的默认超时是100秒,即使您在请求级别设置了更高的值,请求仍然会在此时被取消。要解决此问题,请在HttpClient上设置“max”超时,该超时可以是无限的:

httpClient.Timeout = System.Threading.Timeout.InfiniteTimeSpan;
hkmswyz6

hkmswyz62#

接受的答案是伟大的,但我想给予另一个场景的任何人寻找这个在未来。在我的例子中,我已经使用了一个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;
        }
    }
}
rvpgvaaj

rvpgvaaj3#

如果你已经在使用一个CancellationToken,也许是来自一个异步API端点,你可以使用CancellationTokenSource.CreateLinkedTokenSource将它与另一个CancellationToken组合。
下面是一个例子:

public async Task<HttpResponseMessage> SendRequestWithTimeout(HttpRequestMessage request, Timespan timeout, CancellationToken ct){
    var timeoutCt = new CancellationTokenSource(timeout).Token;
    var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ct, timeoutCt).Token;
    return await httpClient.SendAsync(request, linkedCts);
}

相关问题