Есть ли такой класс C #, как Queue, который реализует IAsyncEnumerable? - PullRequest
1 голос
/ 21 октября 2019

Оба Queue и ConcurrentQueue реализуют IEnumerable, но не IAsyncEnumerable. Существует ли стандартный класс или класс, доступный в NuGet, который реализует IAsyncEnumerable так, что, если очередь пуста, результат MoveNextAsync не завершится, пока в очередь не будет добавлено что-то следующее?

1 Ответ

1 голос
/ 05 ноября 2019

Если вы используете платформу .NET Core, есть как минимум две встроенные опции:

  1. Класс System.Threading.Tasks.Dataflow.BufferBlock<T>, часть TPL Dataflow библиотека. Он не реализует IAsyncEnumerable<T> изначально, но он предоставляет ожидаемый метод OutputAvailableAsync(), что делает его тривиальным для реализации метода расширения ToAsyncEnumerable.

  2. System.Threading.Channels.Channel<T> class, основной компонент библиотеки Channels . Он предоставляет реализацию IAsyncEnumerable<T> с помощью метода Reader.ReadAllAsync() *.

Оба класса также доступны для .NET Framework путем установки пакета nuget (разныедля каждого).

Реализация IAsyncEnumerable<T> для BufferBlock<T>:

public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(
    this IReceivableSourceBlock<T> source,
    [EnumeratorCancellation]CancellationToken cancellationToken = default)
{
    while (await source.OutputAvailableAsync(cancellationToken).ConfigureAwait(false))
    {
        while (source.TryReceive(out T item))
        {
            yield return item;
        }
    }
}

¹ (недоступно для NET Framework, но легко реализовать аналогичным образом)

...