C# 使用HttpCompletionOption.ResponseHeadersRead的HttpClient超时

C# 使用HttpCompletionOption.ResponseHeadersRead的HttpClient超时,c#,http,.net-core,C#,Http,.net Core,在Windows上的.NET Core 3.1控制台应用程序中,我试图找出在使用后获取内容时,httpClient.Timeout似乎不起作用的原因 static async Task Main(字符串[]args) { var httpClient=新的httpClient(); //如果使用HttpCompletionOption,则此超时不起作用 httpClient.Timeout=TimeSpan.FromSeconds(5); var uri=新的uri(“http://broken

在Windows上的.NET Core 3.1控制台应用程序中,我试图找出在使用后获取内容时,
httpClient.Timeout
似乎不起作用的原因

static async Task Main(字符串[]args)
{
var httpClient=新的httpClient();
//如果使用HttpCompletionOption,则此超时不起作用
httpClient.Timeout=TimeSpan.FromSeconds(5);
var uri=新的uri(“http://brokenlinkcheckerchecker.com/files/200MB.zip");
//不会超时
//使用var httpResponseMessage=wait httpClient.GetAsync(uri,HttpCompletionOption.ResponseHeadersRead);
//将在5秒后超时,并出现TaskCanceledException
var httpResponseMessage=等待httpClient.GetAsync(uri);
WriteLine($“状态代码为{httpResponseMessage.StatusCode}。按任意键获取内容”);
Console.ReadLine();
Console.WriteLine(“获取内容”);
var html=await httpResponseMessage.Content.ReadAsStringAsync();
WriteLine($“finished,长度为{html.length}”);
}
还尝试了
CancellationToken

//不会超时
var cts=新的CancellationTokenSource(5000);
使用var httpResponseMessage=wait httpClient.GetAsync(uri,HttpCompletionOption.ResponseHeadersRead,
cts.Token);
ReadAsStreamAsync

//不会超时
使用(Stream streamToReadFrom=wait httpResponseMessage.Content.ReadAsStreamAsync())
{
字符串fileToWriteTo=Path.GetTempFileName();
使用(Stream streamToWriteTo=File.Open(fileToWriteTo,FileMode.Create))
{
等待streamToReadFrom.CopyToAsync(streamToWriteTo);
}
}
我从这篇伟大的文章中了解到了
HttpCompletionOption

更新 使用下面的@StephenCleary将cancellationToken传递到
CopyToAsync
方法中的答案,现在可以按预期工作了

我在下面添加了更新的代码,其中显示了复制到
MemoryStream
中,然后复制到字符串中,我发现这很难找到方法。对于我的用例来说,这很好

stringhtml;
wait using(var streamToReadFrom=wait-httpResponseMessage.Content.ReadAsStreamAsync())
等待使用(var streamToWriteTo=new MemoryStream())
{
等待streamToReadFrom.CopyToAsync(streamToWriteTo,cts.Token);
//注意什么编码-从传入的MIME中读取
html=Encoding.UTF8.GetString(streamToWriteTo.ToArray());
}

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

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


如果此时您不想使用Polly,可以将
取消令牌
传递给
Stream.CopyToAsync

为什么您希望在此处超时?@PavelAnikhouski-问得好!我感兴趣的是为什么在使用HttpCompletionOption时超时行为会发生变化。我也在编写代码,希望在x秒后抛出Http异常,即使客户端仍在成功下载内容。非常感谢。我现在已经用一个有效的答案更新了这个问题。下一步就像我忘记了这个优秀的图书馆一样!