Search code examples
c#.netparallel-extensions

Filtering IEnumerable Pattern


Consider the following simple code pattern:

foreach(Item item in itemList)
{
   if(item.Foo)
   {
      DoStuff(item);
   }
}

If I want to parallelize it using Parallel Extensions(PE) I might simply replace the for loop construct as follows:

Parallel.ForEach(itemList, delegate(Item item)
{
   if(item.Foo)
   {
      DoStuff(item);
   }
});

However, PE will perform unnecessary work assigning work to threads for those items where Foo turned out to be false. Thus I was thinking an intermediate wrapper/filtering IEnumerable might be a reasonable approach here. Do you agree? If so what is the simplest way of achieving this? (BTW I'm currently using C#2, so I'd be grateful for at least one example that doesn't use lambda expressions etc.)


Solution

  • That all factors down to this single line:

    Parallel.ForEach(itemList.Where(i => i.Foo), DoStuff);
    

    But reading a comment to another post I now see you're in .Net 2.0 yet, so some of this may be a bit tricky to sneak past the compiler.

    For .Net 2.0, I think you can do it like this (I'm a little unclear that passing the method names as delegates will still just work, but I think it will):

    public IEnumerable<T> Where(IEnumerable<T> source, Predicate<T> predicate)
    {
       foreach(T item in source)
           if (predicate(item))
              yield return item;
    }
    
    public bool HasFoo(Item item) { return item.Foo; }
    
    Parallel.ForEach(Where(itemList, HasFoo), DoStuff);