我目前正在向Web API提出大量請求。我已嘗試async
這個過程,以便我可以在合理的時間內完成此操作,但是我無法控制連接,因此我不會發送超過10
個請求/秒的連接。我正在使用信號量進行調節,但我不完全確定它在這種情況下會如何工作,因爲我有一個嵌套循環。使用循環限制併發異步請求
我基本上是得到一個模型列表,每個模型都有一個列表中的天數。我需要爲模型內的每一天提出請求。天數可以從1
到約50
,99%
之間的任何時間,它只會是1
。所以我想async
每個模型,因爲會有大約3000
他們,但我想async
日的情況下,有多天需要完成。我需要停留在或低於10
個請求/秒,所以我認爲最好的方法是將整個操作的請求限制設置爲10。有沒有一個地方可以讓信號量限制連接整個鏈條?
每個單獨的請求還必須對2
不同的數據段提出兩個請求,並且此API現在不支持任何類型的批處理。
我對c#很陌生,對async
很新,對WebRequests/HttpClient
很新,所以對此有所幫助。我試圖在這裏添加所有相關的代碼。如果你需要其他東西,請告訴我。
public static async Task GetWeatherDataAsync(List<Model> models)
{
SemaphoreSlim semaphore = new SemaphoreSlim(10);
var taskList = new List<Task<ComparisonModel>>();
foreach (var x in models)
{
await semaphore.WaitAsync();
taskList.Add(CompDaysAsync(x));
}
try
{
await Task.WhenAll(taskList.ToArray());
}
catch (Exception e) { }
finally
{
semaphore.Release();
}
}
public static async Task<Models> CompDaysAsync(Model model)
{
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new
Headers.AuthenticationHeaderValue("Token","xxxxxxxx");
httpClient.Timeout = TimeSpan.FromMinutes(5);
var taskList = new List<Task<Models.DateTemp>>();
foreach (var item in model.list)
{
taskList.Add(WeatherAPI.GetResponseForDayAsync(item,
httpClient, Latitude, Longitude));
}
httpClient.Dispose();
try
{
await Task.WhenAll(taskList.ToArray());
}
catch (Exception e) { }
return model;
}
public static async Task<DateTemp> GetResponseForDayAsync(DateTemp date, HttpClient httpClient, decimal? Latitude, decimal? Longitude)
{
var response = await httpClient.GetStreamAsync(request1);
StreamReader myStreamReader = new StreamReader(response);
string responseData = myStreamReader.ReadToEnd();
double[] data = new double[2];
if (responseData != "[[null, null]]")
{
data = Array.ConvertAll(responseData.Replace("[", "").Replace("]", "").Split(','), double.Parse);
}
else { data = null; };
double precipData = 0;
var response2 = await httpClient.GetStreamAsync(request2);
StreamReader myStreamReader2 = new StreamReader(response2);
string responseData2 = myStreamReader2.ReadToEnd();
if (responseData2 != null && responseData2 != "[null]" && responseData2 != "[0.0]")
{
precipData = double.Parse(responseData2.Replace("[", "").Replace("]", ""));
}
date.Precip = precipData;
if (data != null)
{
date.minTemp = data[0];
date.maxTemp = data[1];
}
return date;
}
我只是在使用'Parallel.ForEach'之前做過類似的事情。使用'ParallelOptions'的重載讓你設置'MaxDegreeOfParallelism',但是你需要先用'Enumerable.SelectMany'將每個模型中的日子變平。 – Biscuits
因此,如果我選擇了很多我的收藏,那麼我會得到一個我所有日子沒有與模型本身關係的大名單,雖然,不是嗎?它是否天生與他們有聯繫,還是我需要做一些特別的事情來確保? – DevDevDev
有一個'SelectMany'的重載,它允許您指定一個結果選擇器來將來自父對象和元素的信息投影到一個新對象中。 'Linq'語法使它更容易工作。請記住,'Parallel.ForEach'讓你以異步的方式運行動作(或任務),你仍然可以在每次迭代中「等待」完成它們。 – Biscuits