Foreach多線程問題


因為以前對天氣的第三方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();

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM