Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.net core 3.1: 'IAsyncEnumerable<string>' does not contain a definition for 'GetAwaiter'

I have a .net core 3.1 console app.

I have a method with the following signature:

public async IAsyncEnumerable<string> GetFilePathsFromRelativePathAsync(string relativePath)

If I call it:

private async Task<IEnumerable<FileUpload>> GetFileUploadsAsync(string relativePath)
{
...
    var filePaths = await service.GetFilePathsFromRelativePathAsync(relativePath);
...
}

I get the following error:

Error CS1061 'IAsyncEnumerable' does not contain a definition for 'GetAwaiter' and no accessible extension method 'GetAwaiter' accepting a first argument of type 'IAsyncEnumerable' could be found (are you missing a using directive or an assembly reference?)

like image 727
Murdock Avatar asked Feb 10 '20 10:02

Murdock


1 Answers

The correct syntax is :

await foreach(var filePath in service.GetFilePathsFromRelativePathAsync(relativePath))
{
    ....
}

An IAsyncEnumerable is used to return a stream of elements that can be processed individually. That's why the feature is actually called async streams, causing quite a bit of confusion

Converting to Task< IEnumerable< FileUpload>>

The best solution would be to not convert, but change the signature to IEnumerable<FileUpload> and return new FileUpload instances as soon as they're created :

private async IAsyncEnumerable<FileUpload> GetFileUploadsAsync(string relativePath)
{
    await foreach(var filePath in service.GetFilePathsFromRelativePathAsync(relativePath))
    {
        var upload = new FileUpload(filePath);
        yield return upload;
    }
}

You can also gather all results, store them in a list and return them, eg with a ToListAsync extension method :

public static async Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> source, CancellationToken cancellationToken=default)
{
    var list = new List<T>();
    await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
    {
        list.Add(item);
    }

    return list;
}

The best code is code you don't write though. The System.Linq.Async project provides LINQ operators for IAsyncEnumerable, including ToList, and can be found on NuGet.

The code is very simple but includes a few optimizations, like using ValueTask instead of Task and special treatment for data that comes from other operators like GroupBy and Reverse, that have to consume the entire IAsyncEnumerable before producing their output.

like image 55
Panagiotis Kanavos Avatar answered Sep 22 '22 22:09

Panagiotis Kanavos