0

I'm having a problem with the .NET HttpClient class. Sometimes the snippet below throws a TaskCanceledException, and i can't debug this because is random (I had the bad luck of Apple reject my Xamarin app for that). Can someone explain to me the reason for this exception?

 public static HttpResultModel RecoveryPassword(string email)
    {
        HttpClient httpClient = new HttpClient();

        try
        {
            var url = String.Format(Constants.SERVER_ADDRESS + "/user/forgotPassword/{0}/", email);

            var request = new HttpRequestMessage(new HttpMethod("POST"), url)
            {
                Content = new StringContent(email, Encoding.UTF8, "application/json"),
            };

            //to be more specific, this line throws the exception
            var result = httpClient.SendAsync(request).Result;

            string message = result.Content.ReadAsStringAsync().Result;

            if (result.IsSuccessStatusCode)
            {
                var response = JsonConvert.DeserializeObject<HttpResultModel>(message);
                response.OperationSuccess = true;
                return response;
            }
            else
            {
                var response = JsonConvert.DeserializeObject<HttpResultModel>(message);
                response.OperationSuccess = false;
                return response;
            }
        }

        catch (Exception ex)
        {
            throw ex;
        }
    }
}
RafaelFerreira
  • 125
  • 1
  • 10
  • 1
    Whenever you see something like this `xxxAsync(...).Result` you can just about guarantee you are doing something wrong – TheGeneral Dec 02 '18 at 03:49
  • so, can I make this method sync in another way? – RafaelFerreira Dec 02 '18 at 03:53
  • Before we can answer that we need to determine what you mean by `make this method sync in another way` do you want this to give your thread back to the thread pool and await for it to return (for scalability, or UI async purposes)? in-turn forcing the `async await` pattern up the call chain. Or do you want to just make this a vanilla synchronous method? – TheGeneral Dec 02 '18 at 03:56
  • I want to UI Thread waits for his return – RafaelFerreira Dec 02 '18 at 03:59
  • however i would consider ditching all the async stuff until you research the appropriate async and await patterns you are just adding more complexity. – TheGeneral Dec 02 '18 at 04:01
  • 1
    @TheGeneral FYI: That answer is not correct (assuming he is using the default `NSUrlSessionHandler`) : https://stackoverflow.com/a/53229363/4984832 – SushiHangover Dec 02 '18 at 04:04
  • @RafaelFerreira If your problem is the timeout, review my answer here: https://stackoverflow.com/a/53229363/4984832 Also blocking the UI thread using `.Result` is really bad, and if you set the timeout to be too long, then iOS will abort your app (and if that happens during Apple's app review, they will of course reject your app, again). As the other comments have stated, you should be using async/await. Also remember that Apple will test your app with no network access, looking for problems like this, you need to test for network access before making https calls. – SushiHangover Dec 02 '18 at 04:11
  • Strange thing that it does not happen all the time... I'm note sure how one can actually succeed (assuming Xamarin SynchronizationContext is similar to WPF/WinForms one). You may want to read https://stackoverflow.com/questions/34151179/async-await-deadlocking-when-using-a-synchronizationcontext (or any similar questions "C# async result wait deadlock") – Alexei Levenkov Dec 02 '18 at 04:33

1 Answers1

0

This is due to either one of the two reasons:

  1. A server disconnection
  2. a timeout by the Http client. The default for HttpClient is 100 seconds. You can set this to an infinite timespan.

    httpClient.Timeout = System.Threading.Timeout.InfiniteTimeSpan;

    each request can be then be set to specific timeouts if needed, as the HttpClient timeout is on a higher level

koolkoda
  • 365
  • 3
  • 6