Параллельное выполнение простого запроса LINQ

Я все еще очень новичок в LINQ и PLINQ. Я обычно просто использую петли и List.BinarySearch во многих случаях, но я пытаюсь выйти из этого мышления, где могу.

public class Staff
{
  // ...
  public bool Matches(string searchString)
  {
    // ...
  }
}

используя "нормальный" LINQ-извините, я не знаком с терминологией - я могу сделать следующее:

var matchedStaff = from s
                     in allStaff
                  where s.Matches(searchString)
                 select s;

но я хотел бы сделать это параллельно:

var matchedStaff = allStaff.AsParallel().Select(s => s.Matches(searchString));

когда я проверяю типа matchedStaff, список bools, чего я не хочу.

прежде всего, что я здесь делаю неправильно, и, во-вторых, как мне вернуть List<Staff> из этого запроса?

public List<Staff> Search(string searchString)
{
  return allStaff.AsParallel().Select(/* something */).AsEnumerable();
}

возвращает IEnumerable<type>, а не List<type>.

2 ответов


для первый вопрос, вы должны просто заменить Select С Where :

var matchedStaff = allStaff.AsParallel().Where(s => s.Matches(searchString));

Select является оператором проекции, не фильтрующий, поэтому вы получаете IEnumerable<bool> соответствует проекции всех ваших объектов персонала из входной последовательности в bools, возвращаемые вашим Matches вызов метода.

я понимаю, что это может быть интуитивно понятным для вас, чтобы не использовать select вообще, как кажется, вы больше знаком с "синтаксисом запроса", где ключевое слово select является обязательным, что не относится к использованию" лямбда-синтаксиса "(или" свободного синтаксиса")... независимо от названия), но так оно и есть;)

операторы проекций, такой Select, принимают за вход элемент из последовательности и преобразуют / проецируют этот элемент как-то на другой тип элемента (здесь проецируют на bool type). Тогда как операторы фильтрации, такие как Where, как введите элемент из последовательности и либо вывести элемент как таковой в выходной последовательности или не опережают элемент вообще, на основе предиката.

что касается вашего второй вопрос, AsEnumerable возвращает IEnumerable как следует из названия ;) Если вы хотите получить List<Staff> можно назвать ToList() (как следует из названия ;)) :

return allStaff.AsParallel().Select(/* something */).ToList();

надеюсь, что это помогает.


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

var matchedStaff = from s in allStaff
    where s.Matches(searchString)
    select s;

параллельный LINQ ( "PLINQ") версия будет:

var matchedStaff = from s in allStaff.AsParallel()
    where s.Matches(searchString)
    select s;

чтобы понять, где bools приходят от, когда вы пишете следующее:

var matchedStaff = allStaff.AsParallel().Select(s => s.Matches(searchString));

это эквивалентно следующему синтаксис:

var matchedStaff = from s in allStaff.AsParallel() select s.Matches(searchString);

как заявил Даркей, если вы хотите использовать синтаксис c# вместо синтаксиса запроса следует использовать Where():

var matchedStaff = allStaff.AsParallel().Where(s => s.Matches(searchString));