Выполнение простого запроса 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
, это список bool
s, который не является тем, что я хочу.
Прежде всего, что я делаю неправильно здесь, а во-вторых, как мне вернуть List<Staff>
из этого запроса?
public List<Staff> Search(string searchString)
{
return allStaff.AsParallel().Select(/* something */).AsEnumerable();
}
возвращает IEnumerable<type>
, а не List<type>
.
Ответы
Ответ 1
Для вашего первого вопроса вы должны просто заменить Select
на Where
:
var matchedStaff = allStaff.AsParallel().Where(s => s.Matches(searchString));
Select
является оператором проектирования, а не фильтрующим, поэтому вы получаете IEnumerable<bool>
, соответствующий проекции всех ваших объектов Staff из входной последовательности в bools, возвращаемые вашим Matches
вызов метода.
Я понимаю, что для вас не может быть интуитивно понятным, чтобы вы не использовали Select
вообще, поскольку кажется, что вы более знакомы с "синтаксисом запроса", где ключевое слово select является обязательным, что не соответствует синтаксису лямбда ( или "свободный синтаксис"... независимо от наименования), но что это такое;)
Операторы прогнозов, такие как Select
, принимают в качестве входных данных элемент из последовательности и преобразуют/проецируют этот элемент каким-то образом на другой тип элемента (здесь проецируется на тип bool
). В то время как операторы фильтрации , такие как Where
, принимают в качестве входных данных элемент из последовательности и либо выводят элемент как таковой в выходной последовательности, либо вообще не выводят элемент на основе предиката.
Что касается вашего второго вопроса, AsEnumerable
возвращает IEnumerable
, как указывает его имя;)
Если вы хотите получить List<Staff>
, вам лучше позвонить ToList()
(как указано в названии;)):
return allStaff.AsParallel().Select(/* something */).ToList();
Надеюсь, что это поможет.
Ответ 2
Нет необходимости отказываться от обычного синтаксиса LINQ для достижения parallelism. Вы можете переписать исходный запрос:
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;
Чтобы понять, откуда приходит bool
, когда вы пишете следующее:
var matchedStaff = allStaff.AsParallel().Select(s => s.Matches(searchString));
Это эквивалентно следующему синтаксису запроса:
var matchedStaff = from s in allStaff.AsParallel() select s.Matches(searchString);
Как указано darkey, если вы хотите использовать синтаксис С# вместо синтаксиса запроса, вы должны использовать Where()
:
var matchedStaff = allStaff.AsParallel().Where(s => s.Matches(searchString));