首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用HttpClient超时的HttpCompletionOption.ResponseHeadersRead

使用HttpClient超时的HttpCompletionOption.ResponseHeadersRead
EN

Stack Overflow用户
提问于 2020-07-20 11:56:32
回答 1查看 1.4K关注 0票数 4

Windows上的.NET核心3.1控制台应用程序,我试图弄清楚为什么httpClient.Timeout在使用HttpCompletionOption.ResponseHeadersRead后获取内容时似乎不起作用

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
// will not timeout
var cts = new CancellationTokenSource(5000);
using var httpResponseMessage = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead,
 cts.Token);

ReadAsStreamAsync

代码语言:javascript
运行
复制
// 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);
    }
}

我从这篇伟大的文章中了解到了HttpCompletionOptionhttps://www.stevejgordon.co.uk/using-httpcompletionoption-responseheadersread-to-improve-httpclient-performance-dotnet

使用@StephenCleary下面的@StephenCleary答案更新,将cancellationToken传递到CopyToAsync方法中,现在,这个方法与预期的一样工作。

我已经包含了下面更新的代码,这些代码显示了复制到一个MemoryStream中然后放入一个字符串中,我发现要找到如何做到这一点很棘手。对于我的用例来说,这很好。

代码语言:javascript
运行
复制
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());
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-20 13:36:00

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

我建议使用波莉超时而不是HttpClient.Timeout;Polly是一个通用库,可用于超时任何操作。

如果此时不想使用Polly,可以将CancellationToken传递给Stream.CopyToAsync

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62994860

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档