HttpClient in using statement causes Task cancelled

后端 未结 2 818
礼貌的吻别
礼貌的吻别 2020-12-30 10:16

I created a FileResult : IHttpActionResult webapi return type for my api calls. The FileResult downloads a file from another url and then returns the stream to

相关标签:
2条回答
  • 2020-12-30 10:49

    I know that if the HttpClient is disposed before the asychronous call is finished the Task's state will change to canceled. However since I use an await in: Content = new System.Net.Http.StreamContent(await httpClient.GetStreamAsync(this.filePath)) that should prevent the HttpClient from being disposed off in the middle of the task completion.

    But what does that task do? It gets the stream. So, your code ends up with a Stream that may or may not be completely read when it closes the HttpClient.

    HttpClient is specifically designed for reuse (and simultaneous use), so I recommend removing the using completely and moving the HttpClient declaration to a static class member. But if you want to close and reopen the clients, you should be able to get it working by reading the stream entirely into memory before closing the HttpClient.

    0 讨论(0)
  • 2020-12-30 10:50

    I had a similar issue with Task Canceled exceptions. If you try catching AggregateException or having a catch all Exception block underneath your WebException, you may well find that you catch it, with one exception with the entry stating "A task was canceled"

    I did some investigation and found that the AggregateException is quite misleading as described in various threads;

    Setting HttpClient to a too short timeout crashes process

    How can I tell when HttpClient has timed out?

    Bug in httpclientgetasync should throw webexception not taskcanceledexception

    I ended up changing my code to set an explicit timeout (where asyncTimeoutInMins is read from the app.config file);

            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;
    
    0 讨论(0)
提交回复
热议问题