使用 HttpCompletionOption.ResponseHeadersRead 的 HttpClient 超时

2024-03-06

Windows 上的 .NET Core 3.1 控制台应用程序,我试图找出为什么httpClient.Timeout使用后获取内容时似乎不起作用HttpCompletionOption.ResponseHeadersRead https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpcompletionoption?view=netcore-3.1

static async Task Main(string[] args)
{
    var httpClient = new HttpClient();

    // if using HttpCompletionOption this timeout doesn't work
    httpClient.Timeout = TimeSpan.FromSeconds(5);

    var uri = new Uri("http://brokenlinkcheckerchecker.com/files/200MB.zip");

    // will not timeout
    //using var httpResponseMessage = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);

    // will timeout after 5s with a TaskCanceledException
    var httpResponseMessage = await httpClient.GetAsync(uri);

    Console.WriteLine($"Status code is {httpResponseMessage.StatusCode}. Press any key to get content");
    Console.ReadLine();
    Console.WriteLine("getting content");

    var html = await httpResponseMessage.Content.ReadAsStringAsync();
    Console.WriteLine($"finished and length is {html.Length}");
}

也尝试过一个CancellationToken

// will not timeout
var cts = new CancellationTokenSource(5000);
using var httpResponseMessage = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead,
 cts.Token);

and ReadAsStreamAsync

// will not timeout
using (Stream streamToReadFrom = await httpResponseMessage.Content.ReadAsStreamAsync())
{
    string fileToWriteTo = Path.GetTempFileName();
    using (Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create))
    {
        await streamToReadFrom.CopyToAsync(streamToWriteTo);
    }
}

我了解到HttpCompletionOption来自这篇伟大的文章:https://www.stevejgordon.co.uk/using-httpcompletionoption-responseheadersread-to-improve-httpclient-performance-dotnet https://www.stevejgordon.co.uk/using-httpcompletionoption-responseheadersread-to-improve-httpclient-performance-dotnet

Update使用下面的@StephenCleary答案将cancelToken传递到CopyToAsync方法现在可以按预期工作。

我在下面包含了更新的代码,其中显示了复制到MemoryStream然后进入一个字符串,我发现很难找到如何做。对于我的用例来说,这很好。

string html;
await using (var streamToReadFrom = await httpResponseMessage.Content.ReadAsStreamAsync())
await using (var streamToWriteTo = new MemoryStream())
{
    await streamToReadFrom.CopyToAsync(streamToWriteTo, cts.Token);
    // careful of what encoding - read from incoming MIME
    html = Encoding.UTF8.GetString(streamToWriteTo.ToArray());
}

我希望HttpClient.Timeout仅适用于GetAsync请求的一部分。HttpCompletionOption.ResponseHeadersRead意思是“考虑Get当读取响应头时完成”,所以它是完整的。所以问题是它不适用于从流中读取。

我建议使用波莉的超时 https://github.com/App-vNext/Polly/wiki/Timeout代替HttpClient.Timeout; Polly 是一个通用库,可用于超时any手术。

如果此时不想使用Polly,可以通过CancellationToken to Stream.CopyToAsync.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 HttpCompletionOption.ResponseHeadersRead 的 HttpClient 超时 的相关文章

随机推荐