因為以前對天氣的第三方API 封裝不夠友好,經常出問題,也很難定位問題的出處,所以近期花了大時間,對天氣的API 進行了重新封裝。一開始只是封裝了一個對位的接口,就是一次只能獲取一個地址的天氣;后來老大Review 代碼后,提出存在多地址的需求,對外就多提供了一個支持都地址查詢的接口,內部其實就是實現一個遍歷的過程。這里就是記錄遍歷發生問題的演變。
最開始代碼,這種方法是單線程的,執行時間非常的長
var result = new List<WeatherModel>();
if (query.Count > 100)
{
throw new WeatherException("Search data cannot exceed 100.");
}
foreach (var query in querys)
{
var weather = await GetWeather(item);
if (weather != null)
{
result.Add(weather);
}
}
經過優化后,這種方法是根據設定的線程數跑,會提速很多
var result = new List<WeatherModel>();
if (query.Count > 100)
{
throw new WeatherException("Search data cannot exceed 100.");
}
Parallel.ForEach(query, new ParallelOptions()
{
MaxDegreeOfParallelism = WeatherConfiguration.MaxDegreeOfParallelism
}, item => Task.Run(async () =>
{
try
{
var weather = await GetWeather(item);
if (weather != null)
{
result.Add(weather);
}
}
catch (Exception ex)
{
GetWeathersException(ex, isNeedException);
}
}).GetAwaiter().GetResult());
上述的方法雖然性能上上來了,但是發現了一個問題,如下圖

最終版
if (query.Count > 100)
{
throw new WeatherException("Search data cannot exceed 100.");
}
return query.AsParallel<WeatherQueryModel>()
.WithDegreeOfParallelism(WeatherConfiguration.MaxDegreeOfParallelism)
.Select<WeatherQueryModel, WeatherModel>(item => GetWeather(item, isNeedException)
.ConfigureAwait(false).GetAwaiter().GetResult() ).ToList();
