I have the following async queue processing routing.
var commandQueue = new BlockingCollection<MyCommand>();
commandQueue
.GetConsumingEnumerable()
.ToObservable(new LimitedConcurrencyLevelTaskPoolScheduler(5))
.Subscribe(c =>
{
try
{
ProcessCommand(c);
}
catch (Exception ex)
{
Trace.TraceError(ex.ToString());
}
}
);
In one specific scenario (when I’m about to get some data), I need to make sure that my commandQueue is empty before going out and getting the data. This operation is expected to happen synchronously. Basically, I want to do something like
public void GetData()
{
commandQueue.WaitForEmpty();
// could potentially be expressed:
// while (commandQueue.Count > 0) Thread.Sleep(10);
return GoGetTheData()
}
I realize that in an ideal scenario, all callers will “GetData” async…but sometimes it’s necessary that it happen in a synchronous manner…and so I need to wait for the command queue to be empty to ensure the consistency and up-to-date-ness of my data.
I know how I can do this pretty easily with a ManualResetEvent…but I’d like to know if there’s an easy way with System.Reactive/TPL.
Thanks.
This is a more difficult question than it seems at first. You want
BlockingCollection(and the underlyingConcurrentQueue) for producer-consumer job semantics. But you also want to be able to observe what’s happening with these collections, including waiting for the ’empty’ signal.Best bet is to take a look at
JobQueueandParallelJobQueuefrom here:http://social.msdn.microsoft.com/Forums/en-US/rx/thread/2817c6e5-e5a4-4aac-91c1-97ba7de88ff7
Which includes an observable for
WhenQueueEmptyand can control the number of simultaneously running jobs and queued jobs (jobs being synonymous in this case with your command concept).