Асинхронное выражение lambda с ожиданием возвращает задачу?

У меня есть следующий код:

            // Get all of the files from the local storage directory.
        var files = await folder.GetFilesAsync();

        // Map each file to a stream corresponding to that file.
        var streams = files.Select(async f => { return await f.OpenStreamForWriteAsync(); });

Я бы ожидал, что streams будет иметь тип IEnumerable<Stream>, но на самом деле он имеет значение IEnumberable<Task<Stream>>, что я и ожидал, если бы я опустил ключевое слово ожидания. Возвращаемый тип OpenStreamForWriteAsync равен Task<Stream> - наверняка ожидая, что он должен создать Stream?

Итак, почему оператор return return возвращает задачу?

Спасибо за вашу помощь.

Ответ 1

Все методы async возвращают либо void, Task, либо Task<TResult>. Лямбда - это просто анонимный метод, и, таким образом, он все еще применяется. Это по сути то же, что и этот метод:

private static async Task<Stream> Foo(TypeGOesHere f )
{
    return await f.OpenStreamForWriteAsync(); 
}

Чтобы вернуть значение Stream, это должен быть метод блокировки, а не метод async:

private static Stream Foo(TypeGOesHere f )
{
    return f.OpenStreamForWriteAsync().Result; 
}

Вероятно, вы этого не хотите.

Вы можете превратить IEnumerable<Task<Stream>> в Task<Stream[]> с помощью Task.WhenAll, если это поможет вам:

Task<Stream[]> resultTask = Task.WhenAll(streams);

Ответ 2

Разве это не лучшее решение?

        // Get all of the files from the local storage directory.
    var files = await folder.GetFilesAsync();

    // Map each file to a stream corresponding to that file and await the Task that waits for all tasks to complete? maybe thats whats being implied above...
    var streams = await Task.WhenAll(files.Select(async f => { return await f.OpenStreamForWriteAsync(); }));