Well 8 years later I hit this very question looking for an Async Queue object myself. I discovered thatand was about to implement the MS created an AsyncQueue<T> class found in nuget package/namespace: Microsoft.VisualStudio.Threading
Docs here: https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.threading.asyncqueue-1?view=visualstudiosdk-2019Thanks to @Theodor Zoulias for mentioning this api may be outdated and the DataFlow lib would be a good alternative.
So I edited my AsyncQueue<> implementation to use BufferBlock<>. Almost the same but works better.
I use this in an AspNet Core background thread like soand it runs fully async.
protected async Task RunMyRun() { AsyncQueue<MyObj>BufferBlock<MyObj> queue = new AsyncQueue<MyObj>BufferBlock<MyObj>(); Task enqueueTask = StartDataIteration(queue); while (!await queue.IsCompletedOutputAvailableAsync()) { var dequeueTaskmyObj = queue.DequeueAsync(); await Task.WhenAnyReceive(dequeueTask, queue.Completion); if (dequeueTask.IsCompletedSuccessfully) { // do something with dequeueTask.Result }myObj } } public async Task StartDataIteration(AsyncQueue<MyObj>BufferBlock<MyObj> queue) { var cursor = await RunQuery(); while(await cursor.Next()) { queue.EnqueuePost(cursor.Current); } queue.Complete(); // <<< signals the consumer when queue.Count reaches 0 } NoteI found that if you are awaiting DequeueAsync whenusing the queue is empty and Complete() is called, a TaskCanceledException will be thrown.
This is why I await both the DequeueAsyncOutputAvailableAsync() Task ANDfixed the queue.Completion Task property, thenissue that I check the dequeue taskhad with AsyncQueue<> IsCompletedSuccessfully prop before touching dequeueTask.Result
You may also want-- trying to throttledetermine when the Enqueue loop (by checking queue.Count). Could run you out of memory fast - but this is true for any async queue scenariowas complete and not having to inspect the dequeue task.