I have an object in my application which performs processing on the items in a collection in a background thread. When the object is created background processing of all existing items in the collection is triggered using the thread pool:
class CollectionProcessor
{
public CollectionProcessor()
{
// Not actually called during the constructor just put it here to simplify the code sample
Action process = new Action(this.Process);
createIndex.BeginInvoke(true, ar => process.EndInvoke(ar), null);
}
void Process()
{
for (int i = 0; i < this.items.Count; i++)
{
this.ProcessItem(this.items[i]);
}
}
}
There is some extra code dotted around for notification callbacks but that is largely the gist of it.
New items can be added to this collection at any time and I need to make sure that those new items are processed – notification of new items is provided by an event which is fired after the items have already been added to the collection. In the event hanlder for this event I need to asynchronously resume the processing of the new items in the collection while also:
- Ensuring that I don’t process the same item twice
- Ensuring that the items are processed in the correct order
- Avoiding queuing up lots of blocked background tasks
I also want to achieve this using a thread pool instead of using a dedicated thread – How should I do this? Obviously assume that access to this.items is thread-safe.
I believe I have figured out a reasonably neat way of doing this. They key is to note that if I had a dedicated background thread performing this processing then the solution is fairly easy and might look a little like this:
The missing link is the
ThreadPool.RegisterWaitForSingleObjectMethod which allows us to convert this to using a thread pool instead of a dedicated thread:This sets up a loop just as before except we aren’t blocking a thread waiting for the reset event.