awaitable Task based queue

前端 未结 9 1184
礼貌的吻别
礼貌的吻别 2020-11-27 14:44

I\'m wondering if there exists an implementation/wrapper for ConcurrentQueue, similar to BlockingCollection where taking from the collection does not block, but is instead a

9条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-27 15:41

    One simple and easy way to implement this is with a SemaphoreSlim:

    public class AwaitableQueue
    {
        private SemaphoreSlim semaphore = new SemaphoreSlim(0);
        private readonly object queueLock = new object();
        private Queue queue = new Queue();
    
        public void Enqueue(T item)
        {
            lock (queueLock)
            {
                queue.Enqueue(item);
                semaphore.Release();
            }
        }
    
        public T WaitAndDequeue(TimeSpan timeSpan, CancellationToken cancellationToken)
        {
            semaphore.Wait(timeSpan, cancellationToken);
            lock (queueLock)
            {
                return queue.Dequeue();
            }
        }
    
        public async Task WhenDequeue(TimeSpan timeSpan, CancellationToken cancellationToken)
        {
            await semaphore.WaitAsync(timeSpan, cancellationToken);
            lock (queueLock)
            {
                return queue.Dequeue();
            }
        }
    }
    

    The beauty of this is that the SemaphoreSlim handles all of the complexity of implementing the Wait() and WaitAsync() functionality. The downside is that queue length is tracked by both the semaphore and the queue itself, and they both magically stay in sync.

提交回复
热议问题