I am trying to ascertain why performance on my blocking collection appears slow. A simple version of my code is illustrated in the question further below.
My question here is if BlockingCollection.TryTake(object,TimeSpan) returns immediately on new data?
TimeSpan gridNextTS = new TimeSpan(0, 0, 60);
if (trPipe.TryTake(out tr, gridNextTS) == false)
From my testing it appears that data is NOT returned immediately. Does that seems likely desired behaviour or am I using it incorrectly?
Detail of code previous question:
A concise benchmark shows that BlockingCollection<T>
does, in fact, perform the handover pretty swiftly regardless of the timeout value supplied to TryTake
.
public async Task BlockingCollectionPerformance()
{
using (var collection = new BlockingCollection<int>())
{
var consumer = Task.Run(() =>
{
var i = 0;
while (collection.TryTake(out i, TimeSpan.FromSeconds(2)))
{
Debug.Print(i.ToString());
}
});
var producer = Task.Run(() =>
{
try
{
for (var i = 0; i < 10; i++)
{
collection.Add(i);
}
}
finally
{
collection.CompleteAdding();
}
});
await Task.WhenAll(producer, consumer);
}
}
The above completes in ~3 ms on my box.
To be more specific though, TryTake
returns quickly whenever an item is added to the collection (and TryTake
returns true
), or when you call CompleteAdding
on the blocking collection (in which case there is no point in waiting out the timeout, and TryTake
returns false
). It is possible to shoot yourself in the foot by keeping the consumer blocked longer than necessary if you never call CompleteAdding
in which case TryTake
will have to wait out the full timeout length before returning false
.