简体   繁体   中英

Using BlockingCollection(T) on existing IProducerConsumerCollection(T)

I'm exposing an IProducerConsumerCollection(T) from an interface that will periodically add items for another thread to consume.

public interface IProducer<T>
{
    IProducerConsumerCollection<T> ProducerCollection { get; }
}

I was trying to use a BlockingCollection(T) with the existing collection, but it appears that adding to the IProducerConsumerCollection(T) directly is not supported:

var queue = new ConcurrentQueue<string>();
var blockingCollection = new BlockingCollection<string>(queue);

var task1 = Task.Run(() => {
    Console.WriteLine("Dequeued " + blockingCollection.Take());
    Console.WriteLine("Dequeued " + blockingCollection.Take());
});

var task2 = Task.Run(() => {
    Console.WriteLine("Enqueueing Hello");
    queue.Enqueue("Hello");

    Console.WriteLine("Enqueueing World");
    queue.Enqueue("World");
});

Task.WaitAll(task1, task2);

This will hang indefinitely as the BlockingCollection(T) will not notice the new items.

Is there similar functionality to the BlockingCollection(T).Take method or is there anything simpler than:

static async Task<T> TakeAsync<T>(
    IProducerConsumerCollection<T> collection,
    CancellationToken token
)
{
    T result;

    while(!collection.TryTake(out result))
    {
        await Task.Yield();
        token.ThrowIfCancellationRequested();
    }

    return result;
}

This will hang indefinitely as the BlockingCollection(T) will not notice the new items.

Indeed - because you're adding directly to queue . From the documentation:

Do not modify the underlying collection directly. Use the BlockingCollection<T> methods to add or remove elements. The BlockingCollection<T> object can become corrupted if you change the underlying collection directly.

So your calls to queue.Enqueue should use blockingCollection instead.

In terms of your TaskAsync - you can use TryTake with a timeout of Infinite (-1) instead... but you might want to read Stephen Cleary's blog post on a similar topic , too...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM