I was reading up on (and experimenting with) the new classes introduced for managing the ThreadPool objects in .NET 4, and they are a nice change from previous versions of the framework. One technique I really like is the Task<generic> implementation. I wrote a test piece of code to implement this using a dictionary object, which acts as an indexed collection of threads. You can view the test code here.

The test code allows the ThreadPool to manage/optimize multiple threads of the same method, and keeps the thread collection in an object that can be expanded as needed. There are cases when the ThreadPool will delay the launch of a thread as part of its optimization, but the dictionary object can queue as many threads ahead of time as it wants to run .  That to me is a powerful combination when the amount of work to do is large, as far as the volume of thread launches is concerned.

The Task<generic> class has a nice way of doing error trapping with the Is_Fault property, combined with the Exception property. Notice the Go() method in the code throws an error on the 20th thread launch.  When the thread manager code detects that Is_Complete, Is_Cancelled or Is_Fault has become true, it first tests the case of Is_Fault and handles that case if true.  If Is_Fault is true, Is_Complete can also be true.. so check for Is_Fault first to avoid thinking Is_Complete means successful.

In this example, I did not attempt reuse of a dictionary item when a thread completes.  A completed Task<generic> value is simply discarded and a new item is created and added to the list.  This should execute any Dispose() method on the thread to ensure it is properly cleaned up.  A possible optimization of this code would be to recycle a completed thread entry.

Try the new classes for yourself.  There is a good overview article of threading in .NET 4 here.