I am using a Blockingcollection
as a FIFO queue
but I am doing a lot of operations on files, where the consumer
may easily encounter a file lock, so what I have done is created a simple try catch where the consumer re-queue's itself, but in a long FIFO queue
with lots of other Items in the queue this is enough of a pause, but in an empty or very short FIFO queue
it means the consumer
perpetually hammers the queue with repeating re-occurrences of itself that are probably going to be still file locked.
i.e.
consumer busy
-> requeue -> consumer busy
-> requeue (ad infinitum)
is there a way to get the BlockingCollection
to not attempt to run the new consumer if it is less than 10 seconds old? i.e. potentially get the net one in the queue and carry on and only take the next consumer if it's createdDateTime is null (default for first attempt) or if it is > 10 seconds?
You could keep two blocking collections: the main one and the "delayed" one. One worker thread would only work on the delayed one, readding them to the main collection. The signature of the rejected collection would be something like:
BlockingCollection<Tuple<DateTime, YourObject>>
now... If the time is fixed at 10 seconds, the delayed collection will nearly be DateTime
sorted (in case of items added nearly at the same time this could be not-true, but we are speaking of milliseconds difference... not a problem)
public class MainClass
{
// The "main" BlockingCollection
// (the one you are already using)
BlockingCollection<Work> Works = new BlockingCollection<Work>();
// The "delayed" BlockingCollection
BlockingCollection<Tuple<DateTime, Work>> Delayed = new BlockingCollection<Tuple<DateTime, Work>>();
// This is a single worker that will work on the Delayed collection
// in a separate thread
public void DelayedWorker()
{
Tuple<DateTime, Work> tuple;
while (Delayed.TryTake(out tuple, -1))
{
var dt = DateTime.Now;
if (tuple.Item1 > dt)
{
Thread.Sleep(tuple.Item1 - dt);
}
Works.Add(tuple.Item2);
}
}
}