2017-01-23 26 views
-3

我編寫了這個代碼,它從一些設備獲取所有這些數據,並將它顯示在Windows窗體應用程序中。而不是依次使用那個foreach循環來查看每個設備,我真的很想一次完成它們。我應該從哪裏開始做到這一點?修改C#代碼來處理多線程

我相信我的主要懸念是列表不是線程安全的,並且能夠從所有不同的設備添加到allPackages列表,因此我可以在最後對其進行排序。這也是一個問題,我需要該方法對於DevicePortal方法是異步的。

我沒有太多的經驗,所以任何和所有的建議,歡迎。

private async void LoadPrograms_Click(object sender, EventArgs e) 
    { 
     this.SetPanelEnabledProperty(false); 
     try 
     { 
      List<packageItem> allPackages = new List<packageItem>(); 

      foreach (Uri uri in uriList) 
      { 
       try 
       { 
        DevicePortal portal = GetPortal(uri); 

        //finds all app packages on the devices 
        DevicePortal.AppPackages apps = await portal.GetInstalledAppPackagesAsync(); 

        foreach (DevicePortal.PackageInfo package in apps.Packages) 
        { 
         allPackages.Add(new packageItem 
         { 
          name = package.Name, 
          packageName = package.FullName 
         }); 
        } 
       } 
       catch (Exception ex) 
       { 
        MessageBox.Show(ex.ToString()); 
       } 
      } 
      //Find all instances of packageNames that have a count > 1 
      IEnumerable<packageItem> duplicates = allPackages 
        .GroupBy(item => item.packageName) 
        .Where(g => g.Count() > 1) 
        .Select(g => g.First()); 

      //populate the second listBox 
      //If there's only one device we ignore the logic we just did and just use all the packages in that device 
      listBox2.DataSource = uriList.Count == 1 ? allPackages : duplicates.ToList(); 
      listBox2.DisplayMember = "name"; 
      listBox2.ValueMember = "packageName"; 
     } 
     finally 
     { 
      this.SetPanelEnabledProperty(true); 
     } 
    } 
+0

對於我來說,在本書中簡單介紹一下C#X(mine is 4.0)這本書。話雖如此,我會看看並行的foreach:https://msdn.microsoft.com/en-us/library/dd460720(v=vs.110).aspx我遠離它的專家,但它對我來說效果很好。 – Trey

回答

0

嘗試這樣的事情,你的每個循環都會調用運行在每個可用線程任務,讓你想你需要一個異步方法。

您可能還想在其中放置一個await命令,以確保在繼續前完成所有任務。

private async void LoadPrograms_Click(object sender, EventArgs e) 
{ 
    this.SetPanelEnabledProperty(false); 
    try 
    { 
    List<packageItem> allPackages = new List<packageItem>(); 

    foreach (Uri uri in uriList) 
    { 
     CallAsyncMethod(uri) 
    } 
    //Find all instances of packageNames that have a count > 1 
    IEnumerable<packageItem> duplicates = allPackages 
      .GroupBy(item => item.packageName) 
      .Where(g => g.Count() > 1) 
      .Select(g => g.First()); 

    //populate the second listBox 
    //If there's only one device we ignore the logic we just did and just use all the packages in that device 
    listBox2.DataSource = uriList.Count == 1 ? allPackages : duplicates.ToList(); 
    listBox2.DisplayMember = "name"; 
    listBox2.ValueMember = "packageName"; 
} 
finally 
{ 
    this.SetPanelEnabledProperty(true); 
} 
} 

private static Task CallAsyncMethod(Uri uri) 
{ 
return Task.Run(() => 
{ 
    try 
    { 
     DevicePortal portal = GetPortal(uri); 

     //finds all app packages on the devices 
     DevicePortal.AppPackages apps = await portal.GetInstalledAppPackagesAsync(); 

     foreach (DevicePortal.PackageInfo package in apps.Packages) 
     { 
      allPackages.Add(new packageItem 
      { 
       name = package.Name, 
       packageName = package.FullName 
      }); 
     } 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.ToString()); 
    } 
}); 
}