具有无限超时的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