2014-10-04 32 views
2

我寫了一個方法,它將元素從很多來源添加到列表中。見下:異步並等待,同時向列表中添加元素<T>

public static async Task<List<SearchingItem>> GetItemsToSelect() 
    { 
     List<SearchingItem> searchingItems = new List<SearchingItem>(); 

     foreach (Place place in await GetPlaces()) 
     { 
      searchingItems.Add(new SearchingItem() { 
       IdFromRealModel=place.Id, NameToDisplay=place.FullName, 
       ExtraInformation=place.Name, TypeOfSearchingItem=TypeOfSearchingItem.PLACE }); 
     } 

     foreach (Group group in await GetGroups()) 
     { 
      searchingItems.Add(new SearchingItem() 
      { 
       IdFromRealModel = group.Id, NameToDisplay = group.Name, 
       ExtraInformation = group.TypeName, TypeOfSearchingItem = TypeOfSearchingItem.GROUP 
      }); 
     } 

     return searchingItems; 
    } 

我測試了這種方法,工作性能。我想它可以工作,因爲GetPlaces方法返回160個元素和GetGroups返回3000.但是,我想知道如果它將工作,如果方法在同一時間返回元素。我應該鎖清單searchingItems

謝謝你的建議。

+0

'我應該鎖定列表searchingItems',否,因爲第二個循環在第一個循環完成之前不會執行。 – 2014-10-04 23:12:36

回答

5

您的物品不會同時運行,您開始GetPlaces(),停止並等待GetPlaces()結果,然後進入第一個循環。然後,您開始GetGroups(),停止並等待GetGroups()結果,然後進入第二個循環。你的循環不是併發的,所以你在添加它們時不需要鎖定。

但是,如果你已經注意到你的兩個異步方法也不是併發的,你可以很容易地修改你的程序來實現它。

public static async Task<List<SearchingItem>> GetItemsToSelect() 
{ 
    List<SearchingItem> searchingItems = new List<SearchingItem>(); 
    var getPlacesTask = GetPlaces(); 
    var getGroupsTask = GetGroups(); 

    foreach (Place place in await getPlacesTask) 
    { 
     searchingItems.Add(new SearchingItem() { 
      IdFromRealModel=place.Id, NameToDisplay=place.FullName, 
      ExtraInformation=place.Name, TypeOfSearchingItem=TypeOfSearchingItem.PLACE }); 
    } 

    foreach (Group group in await getGroupsTask) 
    { 
     searchingItems.Add(new SearchingItem() 
     { 
      IdFromRealModel = group.Id, NameToDisplay = group.Name, 
      ExtraInformation = group.TypeName, TypeOfSearchingItem = TypeOfSearchingItem.GROUP 
     }); 
    } 

    return searchingItems; 
} 

這將完成將開始GetPlaces(),開始GetGroups(),停止並等待GetPlaces()結果,然後去到第一循環,停止並等待GetGroups()結果,然後去到第二個循環。

這兩個循環仍然不是併發的,但是你兩個可以等待的方法可能會給你一個小的性能提升。我懷疑你會從循環並行獲得任何好處,它們似乎只是構建模型,並且使線程安全的開銷並不值得,因爲工作量很少。

如果你真的想嘗試使它更平行(但我懷疑你會看到很多好處)是使用PLINQ來建立你的模型。

public static async Task<List<SearchingItem>> GetItemsToSelect() 
{ 
    var getPlacesTask = GetPlaces(); 
    var getGroupsTask = GetGroups(); 

    var places = await getPlacesTask; 

    //Just make the initial list from the LINQ object. 
    List<SearchingItem> searchingItems = places.AsParallel().Select(place=> 
     new SearchingItem() { 
      IdFromRealModel=place.Id, NameToDisplay=place.FullName, 
      ExtraInformation=place.Name, TypeOfSearchingItem=TypeOfSearchingItem.PLACE 
     }).ToList(); 

    var groups = await getGroupsTask; 

    //build up a PLINQ IEnumerable 
    var groupSearchItems = groups.AsParallel().Select(group=> 
     new SearchingItem() 
     { 
      IdFromRealModel = group.Id, NameToDisplay = group.Name, 
      ExtraInformation = group.TypeName, TypeOfSearchingItem = TypeOfSearchingItem.GROUP 
     }); 

    //The building of the IEnumerable was parallel but the adding is serial. 
    searchingItems.AddRange(groupSearchItems); 

    return searchingItems; 
} 
+0

謝謝你的幫助:) – pbalut 2014-10-04 23:21:15