使用语句中的HttpClient导致任务被取消
我为我的api调用创建了一个FileResult : IHttpActionResult
webapi返回类型。 FileResult从另一个URL下载文件,然后将流返回给客户端。
最初我的代码有一个如下所示的using
语句:
public async Task ExecuteAsync(CancellationToken cancellationToken) { try { HttpResponseMessage response; using (var httpClient = new HttpClient()) { response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new System.Net.Http.StreamContent( await httpClient.GetStreamAsync(this.filePath)) }; } return response; } catch (WebException exception) {...} }
但是,这会间歇性地导致TaskCanceledException
。 我知道如果在异步调用完成之前处理了HttpClient,Task的状态将变为取消。 但是因为我使用了await : Content = new System.Net.Http.StreamContent(await httpClient.GetStreamAsync(this.filePath))
,它应该阻止HttpClient在任务完成过程中被处理掉。
为什么该任务被取消? 这不是因为超时,因为这发生在最小的请求上,并不总是发生在大请求上。
当我删除using
语句时,代码正常工作:
public async Task ExecuteAsync(CancellationToken cancellationToken) { try { HttpResponseMessage response; var httpClient = new HttpClient(); response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new System.Net.Http.StreamContent( await httpClient.GetStreamAsync(this.filePath)) }; return response; } catch (WebException exception) {...} }
知道为什么使用导致了这个问题吗?
我知道如果在异步调用完成之前处理了HttpClient,Task的状态将变为取消。 但是因为我使用了await:Content = new System.Net.Http.StreamContent(等待httpClient.GetStreamAsync(this.filePath)),它应该阻止HttpClient在任务完成过程中被处理掉。
但是这项任务有什么作用? 它得到了流。 因此,您的代码最终会有一个Stream
,当它关闭HttpClient
时可能会或可能不会被完全读取。
HttpClient
专门用于重用(和同时使用),因此我建议完全删除using
并将HttpClient
声明移动到static
类成员。 但是如果你想关闭并重新打开客户端,你应该能够通过在关闭HttpClient
之前将流完全读入内存来使其工作。
我遇到了类似于Task Canceledexception的问题。 如果您尝试捕获AggregateException
或在WebException
下面捕获所有Exception
块,您可能会发现它捕获它,但有一个例外,条目指出“任务已被取消”
我做了一些调查,发现AggregateException
很容易产生误导,如各种线程所述;
将HttpClient设置为太短的超时会导致进程崩溃
我怎么知道HttpClient何时超时?
httpclientgetasync中的错误应该抛出webexception而不是taskcanceledexception
我最终更改了我的代码以设置显式超时(从app.config文件中读取asyncTimeoutInMins
);
string jsonResponse = string.Empty; try { using (HttpClient httpClient = new HttpClient()) { httpClient.BaseAddress = new Uri(Properties.Settings.Default.MyWebService); httpClient.DefaultRequestHeaders.Accept.Clear(); httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); httpClient.Timeout = new TimeSpan(0, asyncTimeoutInMins, 0); HttpResponseMessage response; response = await httpClient.GetAsync("/myservice/resource"); // Check the response StatusCode if (response.IsSuccessStatusCode) { // Read the content of the response into a string jsonResponse = await response.Content.ReadAsStringAsync(); } else if (response.StatusCode == HttpStatusCode.Forbidden) { jsonResponse = await response.Content.ReadAsStringAsync(); Logger.Instance.Warning(new HttpRequestException(string.Format("The response StatusCode was {0} - {1}", response.StatusCode.ToString(), jsonResponse))); Environment.Exit((int)ExitCodes.Unauthorised); } else { jsonResponse = await response.Content.ReadAsStringAsync(); Logger.Instance.Warning(new HttpRequestException(string.Format("The response StatusCode was {0} - {1}", response.StatusCode.ToString(), jsonResponse))); Environment.Exit((int)ExitCodes.ApplicationError); } } } catch (HttpRequestException reqEx) { Logger.Instance.Error(reqEx); Console.WriteLine("HttpRequestException : {0}", reqEx.InnerException.Message); Environment.Exit((int)ExitCodes.ApplicationError); } catch (Exception ex) { Logger.Instance.Error(ex); throw; } return jsonResponse;
- 装饰ASP.NET Web API IHttpController
- Castle Windsor ASP.NET MVC 4和Web API相同的应用程序。 只有MVC控制器没有依赖关系?
- 调整MVC 4 WebApi XmlSerializer以丢失nameSpace
- 如何在NEST2中更新Elasticsearch文档
- ASP.NET Web API – 请求特定的全局变量
- 将WebSockets与ASP.NET Web API一起使用
- 在ASP.Net Web API中的日志记录DelegatingHandler中读取HttpRequestMessage.Content时丢失
- 将IP地址添加到HttpRequestMessage
- AngularJS使用Asp.net Web API:$ http post返回XMLHttpRequest无法加载:预检的响应具有无效的HTTP状态代码405