2017-01-23 2 views
-3

Я написал этот код, который получает все эти данные с некоторых устройств и отображает их в приложении Windows Forms. Вместо того, чтобы смотреть на каждое устройство последовательно с этим циклом 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 (мое 4.0) в двух словах. При этом я рассмотрю параллельный foreach: https://msdn.microsoft.com/en-us/library/dd460720(v=vs.110).aspx Я далек от эксперта, но он хорошо работает для меня. – Trey

ответ

0

Попробуйте что-то вроде этого, ваш для каждого цикла будет вызывать асинхронный метод, который будет выполняться заданием на каждую доступную тему и дать вам хочет вам нужно.

Возможно, вы захотите добавить в команду ожидания команду, чтобы все задачи были выполнены, прежде чем двигаться дальше.

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()); 
    } 
}); 
}