Saltar al contenido

¿Cómo esperar todos los resultados de un IAsyncEnumerable?

Estate atento porque en este tutorial vas a encontrar la contestación que buscas.

Solución:

Una advertencia primero: por definición, una transmisión asíncrona puede no terminar nunca y seguir produciendo resultados hasta que la aplicación termine. Esto es ya utilizado, por ejemplo, en SignalR o gRPC. Los bucles de sondeo también funcionan de esta manera.

Usando ToListAsync en una transmisión asíncrona puede tener consecuencias no deseadas.


Operadores como este ya están disponibles a través del paquete System.Linq.Async.

El consumo de toda la transmisión está disponible a través de ToListAsync. El código es *engañosamente simple, pero oculta algunas cuestiones interesantes:

public static ValueTask> ToListAsync(this IAsyncEnumerable source, CancellationToken cancellationToken = default)

    if (source == null)
        throw Error.ArgumentNull(nameof(source));

    if (source is IAsyncIListProvider listProvider)
        return listProvider.ToListAsync(cancellationToken);

    return Core(source, cancellationToken);

    static async ValueTask> Core(IAsyncEnumerable source, CancellationToken cancellationToken)
    
        var list = new List();

        await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
        
            list.Add(item);
        

        return list;
    

En primer lugar, devuelve un ValueTask. Segundo, asegura que la cancelación sea observada y ConfigureAwait(false) se utiliza para evitar interbloqueos. Finalmente, si la fuente ya ofrece su propia ToListAsync implementación, el operador se remite a eso.

Basado en el comentario de @DmitryBychenko, escribí una extensión para hacer lo que quiero:

    public static async Task> AllResultsAsync(this IAsyncEnumerable asyncEnumerable)
    
        if (null == asyncEnumerable)
            throw new ArgumentNullException(nameof(asyncEnumerable));  

        var list = new List();
        await foreach (var t in asyncEnumerable)
        
            list.Add(t);
        

        return list;
    

Estoy un poco sorprendido de que esto no se haya enviado de forma nativa con C# 8.0… parece una necesidad bastante obvia.

Te mostramos comentarios y puntuaciones

Puedes proteger nuestra publicación escribiendo un comentario o valorándolo te estamos eternamente agradecidos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *