Running a simple LINQ query in parallel

青春壹個敷衍的年華 提交于 2019-12-21 07:12:33

问题


I'm still very new to LINQ and PLINQ. I generally just use loops and List.BinarySearch in a lot of cases, but I'm trying to get out of that mindset where I can.

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

Using "normal" LINQ - sorry, I'm unfamiliar with the terminology - I can do the following:

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

But I'd like to do this in parallel:

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

When I check the type of matchedStaff, it's a list of bools, which isn't what I want.

First of all, what am I doing wrong here, and secondly, how do I return a List<Staff> from this query?

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

returns IEnumerable<type>, not List<type>.


回答1:


For your first question, you should just replace Select with Where :

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

Select is a projection operator, not a filtering one, that's why you are getting an IEnumerable<bool> corresponding to the projection of all your Staff objects from the input sequence to bools returned by your Matches method call.

I understand it can be counter intuitive for you not to use select at all as it seems you are more familiar with the "query syntax" where select keyword is mandatory which is not the case using the "lambda syntax" (or "fluent syntax" ... whatever the naming), but that's how it is ;)

Projections operators, such a Select, are taking as input an element from the sequence and transform/projects this element somehow to another type of element (here projecting to bool type). Whereas filtering operators, such as Where, are taking as input an element from the sequence and either output the element as such in the output sequence or are not outputing the element at all, based on a predicate.

As for your second question, AsEnumerable returns an IEnumerable as it's name indicates ;) If you want to get a List<Staff> you should rather call ToList() (as it's name indicates ;)) :

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

Hope this helps.




回答2:


There is no need to abandon normal LINQ syntax to achieve parallelism. You can rewrite your original query:

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

The parallel LINQ (“PLINQ”) version would be:

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

To understand where the bools are coming from, when you write the following:

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

That is equivalent to the following query syntax:

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

As stated by darkey, if you want to use the C# syntax instead of the query syntax, you should use Where():

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


来源:https://stackoverflow.com/questions/13942998/running-a-simple-linq-query-in-parallel

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!