优化从REST API调用获取数据(超过100个)

本文关键字:超过 100个 数据 获取 REST API 调用 优化 | 更新日期: 2023-09-27 18:03:10

我正试图从我的服务器向另一个服务器公开的REST API进行大量调用,但代码运行时间太长。

下面的代码花费了很多时间。现在我正在使用c# Async/AwaitHTTPClient,有更好的方法可以做到这一点吗?

    static async Task RunAsync()
            {
        HttpClient client = new HttpClient();
                client.BaseAddress = new Uri(URL);
                foreach (var workbk in (workbooksforuserresultingMessage.Items[1] as workbookListType).workbook)
                {
                    if (workbk.project.name == "Ascend")
                    {
                            tsResponse viewresultingMessage = null;
                            //Get View Data 
                            HttpRequestMessage viewrequestMessage = new HttpRequestMessage(HttpMethod.Get, "sites/" + ((siteresultingMessage.Items[0] as siteType).id.ToString()) + "/workbooks/" + workbk.id + "/views");
                            // Add our custom headers
                            viewrequestMessage.Headers.Add("X-Tableau-Auth", (resultingMessage.Items[0] as credentialsType).token.ToString());

                            HttpResponseMessage viewrequestMessageresponse = await client.SendAsync(viewrequestMessage);
                            if (viewrequestMessageresponse.IsSuccessStatusCode)
                            {
                                var viewresponsecontent = await viewrequestMessageresponse.Content.ReadAsStringAsync();
                                XmlSerializer siteserializer = new XmlSerializer(typeof(tsResponse));
                                using (TextReader reader = new StringReader(viewresponsecontent))
                                {
                                   viewresultingMessage = (tsResponse)siteserializer.Deserialize(reader);
                                }
                            }
                    }
                }
                foreach (var workbk in (workbooksforuserresultingMessage.Items[1] as workbookListType).workbook)
                {
                    if (workbk.project.name == "Ascend")
                    {
                        foreach (var vu in workbk.views)
                        {
                            tsResponse viewImageresultingMessage = null;
                            //Get View Data 
                            HttpRequestMessage viewImagerequestMessage = new HttpRequestMessage(HttpMethod.Get, "sites/" + ((siteresultingMessage.Items[0] as siteType).id.ToString()) + "/workbooks/" + workbk.id + "/views/" + vu.id + "/previewImage");
                            // Add our custom headers
                            viewImagerequestMessage.Headers.Add("X-Tableau-Auth", (resultingMessage.Items[0] as credentialsType).token.ToString());

                            HttpResponseMessage viewImagewrequestMessageresponse = await client.SendAsync(viewImagerequestMessage);
                            if (viewImagewrequestMessageresponse.IsSuccessStatusCode)
                            {
                                var viewImageresponsecontent = await viewImagewrequestMessageresponse.Content.ReadAsByteArrayAsync();
                                XmlSerializer siteserializer = new XmlSerializer(typeof(tsResponse));
                                using (var ms = new MemoryStream(viewImageresponsecontent))
                                {
                                    Image returnImage = Image.FromStream(ms);
                                    //return returnImage;
                                }
                            }
                        }
                    }
                }
}

优化从REST API调用获取数据(超过100个)

循环中的那些'await's将序列化请求。考虑在任务上使用. continuewith来处理结果,在数组中跟踪任务,然后调用task。当你设置完所有的并行工作后。

正如@TheESJ所说,等待使您的代码以串行方式执行。也就是说,一旦执行达到第一个await,执行将有效地"暂停",直到Task完成才会恢复。您可以通过不等待Task来避免这种情况,只需将其添加到要跟踪的任务列表中。

为了方便起见,我认为如果你引入一些辅助方法来执行循环体并返回Task,将会有所帮助。

public Task<tsResponse> GetViewString(HttpRequestMessage viewrequestMessage)
   {     
        tsResponse viewresultingMessage = null;
        HttpResponseMessage viewrequestMessageresponse = await client.SendAsync(viewrequestMessage);
        if (viewrequestMessageresponse.IsSuccessStatusCode)
        {
            var viewresponsecontent = await viewrequestMessageresponse.Content.ReadAsStringAsync();
            XmlSerializer siteserializer = new XmlSerializer(typeof(tsResponse));
            using (TextReader reader = new StringReader(viewresponsecontent))
            {
               viewresultingMessage = (tsResponse)siteserializer.Deserialize(reader);
            }
        }
        return viewresultingMessage;
   }
   public Task<tsResponse> GetViewImage(HttpRequestMessage viewImagerequestMessage)
   {     
        tsResponse viewImageresultingMessage = null;
        //Get View Data 
        HttpResponseMessage viewImagewrequestMessageresponse = await client.SendAsync(viewImagerequestMessage);
        if (viewImagewrequestMessageresponse.IsSuccessStatusCode)
        {
            var viewImageresponsecontent = await viewImagewrequestMessageresponse.Content.ReadAsByteArrayAsync();
            XmlSerializer siteserializer = new XmlSerializer(typeof(tsResponse));
            using (var ms = new MemoryStream(viewImageresponsecontent))
            {
                return Image.FromStream(ms);                
            }
        }
   }

然后在主循环中,当方法被启动时,您只需将任务添加到列表中,这实际上是并行执行任务。如果并发连接导致问题,您可能需要增加服务器可以创建的并发连接数。主方法变成。

 static async Task RunAsync()
  {
      HttpClient client = new HttpClient();
      client.BaseAddress = new Uri(URL);
      var tasks = new List<Task<tsResponse>>();
      foreach (var workbk in (workbooksforuserresultingMessage.Items[1] as workbookListType).workbook)
      {
          if (workbk.project.name == "Ascend")
          {
                  tsResponse viewresultingMessage = null;
                  //Get View Data 
                  HttpRequestMessage viewrequestMessage = new HttpRequestMessage(HttpMethod.Get, "sites/" + ((siteresultingMessage.Items[0] as siteType).id.ToString()) + "/workbooks/" + workbk.id + "/views");
                  // Add our custom headers
                  viewrequestMessage.Headers.Add("X-Tableau-Auth", (resultingMessage.Items[0] as credentialsType).token.ToString());
                 tasks.Add(GetViewString(viewrequestMessage);
          }
      }
      foreach (var workbk in (workbooksforuserresultingMessage.Items[1] as workbookListType).workbook)
      {
          if (workbk.project.name == "Ascend")
          {
              foreach (var vu in workbk.views)
              {
                  tsResponse viewImageresultingMessage = null;
                  //Get View Data 
                  HttpRequestMessage viewImagerequestMessage = new HttpRequestMessage(HttpMethod.Get, "sites/" + ((siteresultingMessage.Items[0] as siteType).id.ToString()) + "/workbooks/" + workbk.id + "/views/" + vu.id + "/previewImage");
                  // Add our custom headers
                  viewImagerequestMessage.Headers.Add("X-Tableau-Auth", (resultingMessage.Items[0] as credentialsType).token.ToString());
                  tasks.Add(GetViewImage(viewImagerequestMessage);
              }
          }
      }
      // wait for all the tasks to complete (non blocking)
      await Task.WhenAll(tasks);
}