Andy's observations as he continues to attempt to know all that is .NET...

Friday, August 14, 2009

Fluent Parallel While

During devweek 2009 Oliver introduced me to Fluent Api's, I personally love programs that naturally read, after all programs are read far more often than written.  This week a posting on the Parallel Extensions blog demonstrated how to achieve parallel while, since we only have Parallel.For and Parallel.ForEach

 

static void Main(string[] args)
{
ConcurrentQueue<int> queue = new ConcurrentQueue<int>();

for (int i = 0; i < 10; i++)
{
queue.Enqueue(i);
}


Action<ParallelLoopState> processQueue = (lps) =>
{
int item;
if (queue.TryDequeue(out item))
{
Console.WriteLine(" Thread Id = {0} Task Id = {1} : {2}", Thread.CurrentThread.ManagedThreadId, Task.Current.Id, item);
}
};

Func<bool> queueContainsItems = () => queue.IsEmpty == false;

ParallelUtil.While(new ParallelOptions(), queueContainsItems, processQueue);
}





I thought I’d combine both these ideas and produce what I would consider a more  Fluent version




public static class ParallelUtil
{
private static IEnumerable<bool> Infinite()
{
while (true) yield return true;
}

private static ParallelOptions NoParallelOptions = new ParallelOptions();

public static void InParallelWhile(this Action<ParallelLoopState> action, Func<bool> condition, ParallelOptions options = null)
{
if (options == null) options = NoParallelOptions;

Parallel.ForEach(IterateForever(), options ,
(ignored, loopState) =>
{
if (!condition())
{
loopState.Stop();
}
else
{
action(loopState);
}
});

}

private static IEnumerable<bool> IterateForever()
{
while (true)
{
yield return true;
}
}
}
class Program
{
static void Main(string[] args)
{
ConcurrentQueue<int> queue = new ConcurrentQueue<int>();

for (int i = 0; i < 10; i++)
{
queue.Enqueue(i);
}


Action<ParallelLoopState> processQueue = (lps) =>
{
int item;
if (queue.TryDequeue(out item))
{
Console.WriteLine(" Thread Id = {0} Task Id = {1} : {2}", Thread.CurrentThread.ManagedThreadId, Task.Current.Id, item);
}
};

Func<bool> queueContainsItems = () => queue.IsEmpty == false;

processQueue.InParallelWhile(queueContainsItems);
}
}
}









The key difference is the first example you use the following line to process the queue in parallel



ParallelUtil.While(new ParallelOptions(), queueContainsItems, processQueue);



As opposed to the second version with a perhaps more fluent implementation



processQueue.InParallelWhile(queueContainsItems);

About Me

My photo
Im a freelance consultant for .NET based technology. My last real job, was at Cisco System were I was a lead architect for Cisco's identity solutions. I arrived at Cisco via aquisition and prior to that worked in small startups. The startup culture is what appeals to me, and thats why I finally left Cisco after seven years.....I now filll my time through a combination of consultancy and teaching for Developmentor...and working on insane startups that nobody with an ounce of sense would look twice at...