views:

47

answers:

1

I implements a producer-consumer pattern using C#'s TPL. The scenario is described as below.

I have a task who produces jobs to a BlockingCollection. The collection has a capacity limit, say, 3 jobs maximally. I have two consumer tasks who try to get jobs from the collection and execute them. I also implement a cancellation to the producer and consumers. For producer, when it detects cancellation, it will call BlockingCollection.CompleteAdding(), which allows the consumers to finish waiting.

Now it is possible that:

Time 1: The producer puts 2 jobs in the collection;

Time 2: Two consumers grab the jobs and run themselves;

Time 3: The producer puts another 3 jobs in the collection. Since it meets the capacity of the collection, the producer goes to asleep;

Time 4: The cancellation happens on the two consumers. They stop.

Now the producer sleeps forever because no one works on the jobs. How to handle the cancellation on consumers so they can sort of wake up the producer?

What I can think of is put the below code in the cancellation handler of the consumers.

lock(BlockingCollection){
    if(BlockingCollection.BoundedCapacity == BlockingCollection.Count) BlockingCollection.Take();
}

Since there are more than one consumer, it has to lock the collection. The extra take is only necessary when the BlockingCollection.BoundedCapacity equals to the number of items in it. This extra take will empty one slot in the collection and thus trigger the producer to wake up, detect the cancellation itself.

Is this correct?

+1  A: 

I would use the cancellable overload of Add: http://msdn.microsoft.com/en-us/library/dd381879.aspx

When you cancel the consumers you can also ensure that the producer is cancelled by triggering the cancellation token either at the same time, or in the consumer threads.

Anthony Williams
A good point. I read this overload before and am not sure whether it is still working when the Add method is called with the token not being canceled and the thread is put to asleep and later the token is canceled by a consumer. Now it seems that this overload can bring asleep producer back to work when the token is canceled, which is what I am looking for.
Steve