优化从REST API调用获取数据(超过100个)
本文关键字:超过 100个 数据 获取 REST API 调用 优化 | 更新日期: 2023-09-27 18:03:10
我正试图从我的服务器向另一个服务器公开的REST API进行大量调用,但代码运行时间太长。
下面的代码花费了很多时间。现在我正在使用c# Async/Await
和HTTPClient
,有更好的方法可以做到这一点吗?
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;
}
}
}
}
}
}
循环中的那些'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);
}