如何等待特定的 http 状态代码 - C#

问题描述

我已经实现了这段代码,现在两周了。从那时起,我试图改进我的代码,因为有时 Task.Delay 方法不足以等待 3rd 方 API 发送我需要的正确 http 状态代码。 (他们的处理时间比我预期的要长得多。)

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 }");
}

正如您在我的代码中看到的,我设置了 20,000 毫秒(20 秒)的延迟来处理逻辑,并期望在这段时间内完成该过程并且我可以获得正确的响应和值。

无论如何,我该如何改进或使其像回调或我仍然没有发现的东西一样工作。

谢谢!

解决方法

我假设 API 是这样工作的:

  1. 您发布一个帖子,这会在服务器上启动一些计算。
  2. 您使用从 Post 返回的 url 进行 Get。如果计算完成,这将成功,否则将失败。

要管理这个,你应该使用轮询,即

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
     }
 }

如果服务器从不响应,您可能还应该添加超时或检查返回的错误代码类型以避免永远轮询。

如果您可以更改 API,那么使用某种 callback 而不是使用轮询也可能是有意义的,因为回调通常会导致使用更少的资源。