使用 HttpClientHandler 设置超时

Set timeout with HttpClientHandler

我正在尝试使用 HttpClientHandler 设置 anglesharp.io 的超时值。

这个问题表明有可能:https://github.com/AngleSharp/AngleSharp/issues/266

我得到这样的页面:

        NetworkCredential proxyCreds = new NetworkCredential(proxy.User, proxy.Pass);

        WebProxy wProxy = new WebProxy(proxy.Ip + ":" + proxy.Port, false)
        {
            UseDefaultCredentials = false,
            Credentials = proxyCreds,
        };

        HttpClientHandler httpClientHandler = new HttpClientHandler()
        {
            Proxy = wProxy,
            PreAuthenticate = true,
            UseDefaultCredentials = false
        };

        var config = Configuration.Default.WithRequesters(httpClientHandler);

        var document = await BrowsingContext.New(config).OpenAsync(address);

我看不到任何可用于设置超时的属性。如何设置超时时间?

上面的评论是正确的。 AngleSharp 正在将请求者抽象出来——以允许多种类型的请求者并在需要时提供灵活性。基本接口是 IRequester(注意:故意没有 HTTP - 在 AngleSharp.Io 中我们还发现,例如,一个 FileRequester 访问本地文件系统的 file:// URI) .

我们现在可以实现我们自己的请求器,或者只使用来自 AngleSharp.Io 的 HttpClientRequester 以及接受 HttpClient 实例的构造函数重载。

var client = new HttpClient();
client.Timeout = MyCustomTimeout; //Whatever value you want it to be
var requester = new HttpClientRequester(client);

现在的问题是如何使用这个请求器?我们只是创建一个配置(像往常一样)并使用默认加载程序扩展方法(像往常一样),但是,这次使用我们的自定义请求器。

对于 0.10 之前的版本,它看起来如下:

 // Assumes we do not want to provide custom options for the loaders
 var requesters = new [] { requester };
 var configuration = Configuration.Default.WithDefaultLoader(requesters: requesters);

对于 0.10 及更高版本,这看起来有点不同:

 var configuration = Configuration.Default.WithRequester(requester).WithDefaultLoader();

希望对您有所帮助!

有时需要在 HttpClientHttpClientHandler 级别上设置不同的超时,例如某种重试逻辑,HttpClient 无缝 - 等待 5 分钟,然后重试每一分钟。在这种情况下,可以使用如下委托处理程序:

public class RetryHandler : DelegatingHandler
{
    private readonly TimeSpan timeout;

    public RetryHandler(TimeSpan timeout)
    {
        this.timeout = timeout;
    }

    private async Task<HttpResponseMessage> Delay(
        CancellationToken cancellationToken)
    {
        await Task.Delay(timeout, cancellationToken);

        return null;
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        for (; ; )
        {
            cancellationToken.ThrowIfCancellationRequested();

            var delayTask = Delay(cancellationToken);
            var firstCompleted = await Task.WhenAny(
                base.SendAsync(request, cancellationToken), delayTask);

            if (firstCompleted != delayTask)
                return await firstCompleted;
        }
    }
}

用例:

var client = new HttpClient(
new RetryHandler(TimeSpan.FromMinutes(1)))
{
    Timeout = TimeSpan.FromMinutes(5)
};

client.PostAsync(...);