0

I have implemented this code, since 2 weeks now. Since then I am trying to improve my code because sometimes the Task.Delay method is not enough to wait the third party API to send the correct http status code that I needed it. (They process is much longer than what I expected.)

var url = string.Format(_azureFormRecognizerConfig.RequestUrl, _azureFormRecognizerConfig.ResourceUrl, modelId);
var content = new StringContent(JsonConvert.SerializeObject(new { source = storagePath }), Encoding.UTF8, _azureFormRecognizerConfig.MediaType);

using (var httpClient = new HttpClient())
{
    // Request headers
    httpClient.DefaultRequestHeaders.Add(_azureFormRecognizerConfig.SubscriptionType, _azureFormRecognizerConfig.SubcriptionKey);

    using (var response = await httpClient.PostAsync(url, content))
    {
        try
        {
            response.EnsureSuccessStatusCode();
            responseLocationUri = response.Headers.GetValues("Operation-Location").FirstOrDefault();
        }
        catch (HttpRequestException ex)
        {
            _logger.Information($"Error in httpclient { ex.Message } ");
        }
    }

    Task.Delay(20000).Wait();

    using (var response = await httpClient.GetAsync(responseLocationUri))
    {
        try
        {
            response.EnsureSuccessStatusCode();
            responseBody = await response.Content.ReadAsStringAsync();

        }
        catch (HttpRequestException ex)
        {
            _logger.Information($"Error in httpclient { ex.Message } ");
        }
    }

    _logger.Information($"Response headers { responseBody }");
}

As you can see in my code, I put a delay of 20,000 milliseconds (20seconds) just to handle the logic and expect that within that time the process is done and I can get the correct response and value.

Is there anyway, how can I improve this or make it work like a callback or something that I still didn't discover.

18
  • 1
    I don't see any value in the call to delay. You are awaiting the GetAsync so either it will return when its ready or timeout independent of the delay. Commented Feb 22, 2021 at 15:48
  • 1
    your try-catch block does not include the await GetASync call, youu may want to change it. Commented Feb 22, 2021 at 15:48
  • 4
    Task.Delay(20000).Wait(); Using Wait() on a Task is asking for trouble. Since you're already in an async function, use await Task.Delay(20000); instead. Commented Feb 22, 2021 at 16:04
  • 1
    The problem here is that your 20 seconds is entirely arbitrary. You don't know exactly (from this code) how long that api will need before your second call. It has nothing to do with "response codes". Does that api have another call you can make which reports when it has processed whatever you need it to process? If not, the best you can do is keep trying until you get the response you're after. Commented Feb 22, 2021 at 16:06
  • 1
    Not being rude, but have you tried the docs because it's unlikely you're the first person to hit this problem. Commented Feb 22, 2021 at 16:09

1 Answer 1

1

I would assume the API works as this:

  1. You make a Post, this starts some computation on the server.
  2. You make a Get with a url returned from the Post. This will succeed if the computation is finished, and fail otherwise.

To manage this you should use polling i.e.

while(true){
    using (var response = await httpClient.GetAsync(responseLocationUri)){
         if(response.IsSuccessStatusCode){
               // Handle success case
               return someResult;
          }
          await Task.Delay(1000); // Wait 1s between each attempt
     }
 }

You should probably also add a timeout or check the type of error code returned to avoid polling forever if the server never responds.

If you can change the API it might also make sense to use some kind of callback instead of using polling, since callbacks usually result in less resources being used.

Sign up to request clarification or add additional context in comments.

3 Comments

I understand now, this is what I needed. Already have an idea on how to improve my code. Thank you so much.
Why don't you use HEAD? This implementation can stuck in the loop infinitely. It would be wise to maximize the retry count.
@Peter Csala The example is simplified to show the main point. But I do mention that some way to avoid a infinite loop would be needed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.