I’ve pretty much finished my thread pool implementation for the service I’m writing, and generally I’m quite pleased with it. It was inspired by these 2 articles from Code Project
Although it’s for a particular application purpose, I tried to develop it to be as flexible as possible and so can support features such as: –
- Minimum/Maximum number of worker threads
- Upon pool shutdown, workers can be instructed to wait for their tasks to finish indefinitely aborted immediatley
- Work tasks that are aborted or throw exceptions can be requeued or not
- Upon thread pool restart the pool can add new handlers to service extant work tasks progressively or in a “frenzy”
- State information is publishable via WMI, and supports multiple instances of the thread pool
- Configurable determination of when additional threads are required, or when surplus threads can be shutdown
Virtually all the thread pool behaviour is controlled by a user supplied policy object in tandem with the state information (configuration) set on the thread pools state object.
As for the threading model used, I opted for the Thread/ThreadStart model as opposed to the ThreadPool.QueueUserWorkItem method, simply because it allowed more control and flexability in the resultant “scheduling” service. The thread pool class exposes a relatively simple interface contain lists of work threads and work tasks. Worker threads are encapsulated within a seperate class which is responsible for starting and shutting down the actual Thread object and contains the ThreadStart procedure delegate.
In this version, after a client has submitted a work task, there is no way the client can ask the thread pool whether a task has completed, they would have to include that behaviour within their task object themselves. To submit a work task, a client simply supplies a callback method compatible with the WaitCallback delegate, and an optional context Object that is passed to the callback when a work thread executes the callback. This infers that the callback method supplied has a method signature like
public void someCallBackMethod(Object context)
This is not enforced however, through the use of a WorkItem interface, for instance. Although this is perhaps somewhat lax, I traded flexability in this respect over “safety”. The thread pool itself is thread safe and can be safely referenced from multiple threads, as can the thread pools state object. Because the state object itself can be accessed from multiple threads and often frequently I decided to make it thread safe only when used as shown: –
// get or set state information
The only reason for this was performance, given that you may want to access multiple elements of the state object consecutively, it’s more efficient to lock once, and it means that you are able to get or set multiple elements of state information atomically.
The State object, in this version, is created by the thread pool class, but there is no reason why this could not be created by a client user and supplied to the thread pool upon object creation, since the state object is accessed via an interface.
Well thats about it, if anyone’s interested in the source, just send me a mail. I might possibly write a CodeProject article about it but this subject has seemingly been done to death on CodeProject, so I’m not sure what else this would contribute.