title: Is there a data structure in C# like a ConcurrentQueue which allows me to await an empty queue until an item is added?
body: <p>I'm looking for an object like a ConcurrentQueue which will allow me to await the Dequeue operation if the queue is empty so I can do something like the following:</p>
  
  <pre class="lang-cs prettyprint-override"><code>public static async Task ServiceLoop() {
  
      var awaitedQueue = new AwaitedQueue&lt;int&gt;();
  
      while (!cancelled) {
          var item = await awaitableQueue.Dequeue();
          Console.WriteLine(item);
      }
  
  }
  </code></pre>
  
  <p>I've written the following class, but if an item is added to the queue between the time Dequeue is called and a new awaiter is Enqueued, terrible things will happen.</p>
  
  <pre class="lang-cs prettyprint-override"><code>public class AwaitedQueue&lt;T&gt; : IDisposable {
  
      ConcurrentQueue&lt;TaskCompletionSource&lt;T&gt;&gt; awaiters = new ConcurrentQueue&lt;TaskCompletionSource&lt;T&gt;&gt;();
  
      ConcurrentQueue&lt;T&gt; items = new ConcurrentQueue&lt;T&gt;();
  
      public AwaitedQueue() { }
  
      public void Enqueue(T item) {
          if (!awaiters.TryDequeue(out TaskCompletionSource&lt;T&gt; awaiter)) {
              this.items.Enqueue(item);
          } else {
              awaiter.SetResult(item);
          }
      }
  
      public async Task&lt;T&gt; Dequeue() {
          if (items.TryDequeue(out T item)) {
              return item;
          } else {
              // If an item is enqueued between this call to create a new TaskCompletionSource.
              var awaiter = new TaskCompletionSource&lt;T&gt;();
              // And this call to actually enqueue, I believe it will cause me problems.
              awaiters.Enqueue(awaiter);
              return await awaiter.Task;
          }
      }
  
      public void Dispose() {
          while (awaiters.TryDequeue(out TaskCompletionSource&lt;T&gt; awaiter)) {
              awaiter.SetCanceled();
              awaiter.Task.Wait();
          }
      }
  }
  </code></pre>
  
  <p>I'm sure a robust and well-tested implementation of this concept already exists, but I don't know which combination of English words I need to type into Google to find it.</p>