Skip to content

Instantly share code, notes, and snippets.

@ReubenBond
Last active July 2, 2018 07:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ReubenBond/98de2cede0d57a989ededa8e113b0f39 to your computer and use it in GitHub Desktop.
Save ReubenBond/98de2cede0d57a989ededa8e113b0f39 to your computer and use it in GitHub Desktop.
Demonstrates an InvalidOperationException when using BlockingCollection with ConcurrentBag as the underlying collection and calling TryTakeFromAny
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace BlockingCollectionConcurrentBagException
{
class Program
{
static void Main(string[] args)
{
// We only hold a reference to the outer BlockingCollection, not the inner ConcurrentBag
var blockingCollection = new BlockingCollection<int>(new ConcurrentBag<int>());
// Produce elements into the collection.
var i = 0;
var producerFunc = new WaitCallback[1];
producerFunc[0] =
state =>
{
if (blockingCollection.Count == 0) blockingCollection.Add(i++);
else Thread.Yield();
ThreadPool.QueueUserWorkItem(producerFunc[0]);
};
ThreadPool.QueueUserWorkItem(producerFunc[0]);
// Concurrently pull elements off the collection.
var consumerFunc = new WaitCallback[1];
consumerFunc[0] =
ignored =>
{
var success = false;
do
{
try
{
// THIS IS WHERE THE EXCEPTION OCCURS
success = blockingCollection.TryTake(out _);
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
} while (success);
ThreadPool.QueueUserWorkItem(consumerFunc[0]);
};
// Start two competing consumers.
ThreadPool.QueueUserWorkItem(consumerFunc[0]);
ThreadPool.QueueUserWorkItem(consumerFunc[0]);
Thread.Sleep(-1);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment