Csharp/C#教程:具有无限超时的HttpClient会抛出超时exception分享


具有无限超时的HttpClient会抛出超时exception

我的HttpClient使用摘要式身份validation连接到服务器,并期望响应搜索查询。 这些搜索查询可以随时进入,因此客户端应始终保持连接处于打开状态。

使用以下代码建立连接:

public static async void ListenForSearchQueries(int resourceId) { var url = $"xxx/yyy/{resourceId}/waitForSearchRequest?token=abc"; var httpHandler = new HttpClientHandler { PreAuthenticate = true }; using (var digestAuthMessageHandler = new DigestAuthMessageHandler(httpHandler, "user", "password")) using (var client = new HttpClient(digestAuthMessageHandler)) { client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite); var request = new HttpRequestMessage(HttpMethod.Get, url); var tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(TimeSpan.FromMilliseconds(Timeout.Infinite)); using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, tokenSource.Token)) { Console.WriteLine("nResponse code: " + response.StatusCode); using (var body = await response.Content.ReadAsStreamAsync()) using (var reader = new StreamReader(body)) while (!reader.EndOfStream) Console.WriteLine(reader.ReadLine()); } } } 

这是在控制台应用程序的Main方法中使用该方法的方法。

 private static void Main(string[] args) { const int serviceId = 128; . . . ListenForSearchQueries(resourceId); Console.ReadKey(); } 

这是控制台窗口上的输出如下所示:

 Response code: OK --searchRequestBoundary 

即使客户端的超时设置为无穷大,连接在第一次输出后大约五分钟(这不是HttpClient的默认超时)后超时,抛出以下exception。

 System.IO.IOException occurred HResult=0x80131620 Message=The read operation failed, see inner exception. Source=System.Net.Http StackTrace: at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.Read(Byte[] buffer, Int32 offset, Int32 count) at System.Net.Http.DelegatingStream.Read(Byte[] buffer, Int32 offset, Int32 count) at System.IO.StreamReader.ReadBuffer() at System.IO.StreamReader.get_EndOfStream() at ConsoleTester.Program.d__10.MoveNext() in C:UsersxyzProjNameConsoleTesterProgram.cs:line 270 Inner Exception 1: WebException: The operation has timed out. 

用于身份validation的DelegateHandler是对此代码的粗略调整(请参阅源代码部分)。

为什么客户端超时,我该如何防止这种情况发生?

我的最终目标是打个电话并无限期地等待回应。 当响应确实到来时,我不希望关闭连接,因为将来可能会有更多响应。 不幸的是,我无法在服务器端更改任何内容。

虽然Stream.CanTimeout的默认值为false ,但是通过response.Content.ReadAsStreamAsync()返回流会给出CanTimeout属性返回true的流。

此流的默认读取和写入超时为5分钟 。 这是在五分钟不活动之后,流将抛出exception。 与问题中显示的例外非常相似。

若要更改此行为,可以调整流的ReadTimeout和/或WriteTimeout属性。

下面是ListenForSearchQueries方法的修改版本, ListenForSearchQueries ReadTimeout更改为Infinite。

 public static async void ListenForSearchQueries(int resourceId) { var url = $"xxx/yyy/{resourceId}/waitForSearchRequest?token=abc"; var httpHandler = new HttpClientHandler { PreAuthenticate = true }; using (var digestAuthMessageHandler = new DigestAuthMessageHandler(httpHandler, "user", "password")) using (var client = new HttpClient(digestAuthMessageHandler)) { client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite); var request = new HttpRequestMessage(HttpMethod.Get, url); var tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(TimeSpan.FromMilliseconds(Timeout.Infinite)); using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, tokenSource.Token)) { Console.WriteLine("nResponse code: " + response.StatusCode); using (var body = await response.Content.ReadAsStreamAsync()) { body.ReadTimeout = Timeout.Infinite; using (var reader = new StreamReader(body)) while (!reader.EndOfStream) Console.WriteLine(reader.ReadLine()); } } } } 

这修复了实际被流抛出的exception,但似乎被HttpClient抛出了。

使方法返回一个Task

 public static async Task ListenForSearchQueries(int resourceId) { //...code removed for brevity } 

更新控制台的主要方法以Wait Task完成。

上述就是C#学习教程:具有无限超时的HttpClient会抛出超时exception分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

 public static void Main(string[] args) { const int serviceId = 128; . . . ListenForSearchQueries(resourceId).Wait(); Console.ReadKey(); } 

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/1039024.html

(0)
上一篇 2022年1月26日
下一篇 2022年1月26日

精彩推荐