Saturday, September 18, 2010

TEAM.Commons: Threading - part 2

This is the 5th of several posts about TEAM.Common, a set of functionality I use in every project and that I'd like to share. The index is here:

In TEAM.Common.Threading you can find these abstractions:

A thread running a task in an "infinite" loop, until some other thread asks it to stop.
This is a very basic piece I use it all the time for implementing services and it's also the foundation for the "advanced" features.

public abstract class WorkerThread
 Exception Error { get; }
 void ForceStop();
 bool IsStopped { get; }
 void Start();
 void Stop();
 event EventHandler<System.ComponentModel.RunWorkerCompletedEventArgs> Stopped;

My approach to parallelization was to use the one producer -> several consumers technique:
You must create an instance of this class passing an instance of IProducer and a list of IConsumerWorker.

public class ProducerConsumersProcess<T>
    int ConsumedItemsCount { get; }
    int ProducedItemsCount { get; }
    void Start();

With a very simple interface, ProducerConsumersProcess<T> coordinates the producer and the consumers using a buffer (an InProcessTransport, see next post) and handling a lot of edge cases and exceptions.


public interface IProducer<T>
    T ProduceOne();
    bool HasFinished();


public interface IConsumerWorker<T>
    event EventHandler<RunWorkerCompletedEventArgs> Stopped;
    void Start(IReceivingTransport receivingTransport);
    void StopWhenStarved();
    void InterruptExecution();
    bool IsStopped { get; }
    int ProcessedItemsCount { get; }
    Exception Error { get; }
    string Id { get; }

These are the foundations for all the good stuff. The rest are classes that help in the most common cases:

Just pass two delegates:

public DelegatedProducer(Func<T> producerDelegate, Func<bool> hasFinishedDelegate)
Combine it with lambda expressions and you have a very flexible and expressive syntax.

Just pass an IEnumerable:

public EnumeratorProducer(IEnumerable<T> enumerableSource)
Combine it with the yield operator and/or lambda expressions and again, you have a very flexible and expressive syntax.

Just pass an IEnumerable:

public DelegatedConsumerWorker(string id, TimeSpan starvationTimeOut, int processedItemsCountMonitorizationStep, Action<T> consumerDelegate)
You know what comes now: mix it with lambda expressions and...

Remember, you can get all this code for free at bitbucket:

Check it out to get ideas, or simply use it as it is. It's working out for me and my team.

No comments: