【问题标题】:Async lambda expression with await returns Task?带有等待的异步 lambda 表达式返回任务?
【发布时间】:2016-12-13 20:29:21
【问题描述】:

我有以下代码:

            // 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(); });

我希望streamsIEnumerable<Stream> 类型,但实际上它是IEnumberable<Task<Stream>>,如果我省略了await 关键字,这是我所期望的。 OpenStreamForWriteAsync 的返回类型是 Task<Stream> — 肯定在等待它应该产生 Stream?

那么,为什么 return await 语句会返回一个 Task?

感谢您的帮助。

【问题讨论】:

  • 异步方法总是返回Task<T>Task。 Select 本身并不关心返回类型。因此它会投射一个可枚举的任务,因为您选择的 lambda 是异步的。您可以遍历您的集合并等待 Stream。
  • 好吧,我们可以编写一个“async void”方法,这就是我认为这里发生的事情。我该如何解决?
  • @MatthewH 如果是void,您将不知道异步任务何时完成并且无法获得任何结果(因为不会有任何结果)。当它是一个事件处理程序时,你真的只想拥有一个 void async 方法,但事实并非如此。
  • @MatthewH vscjones 可能的意思是,只要您有一个返回 void 的非async 方法并将其转换为 async 方法,您应该将其返回类型从 void 更改为Task,因为Task 是调用者知道何时完成的一种方式,但表明它没有结果。返回void 只是意味着调用者甚至不知道它何时结束。
  • why is the return await statement returning a Task? 我 +1'ed Servy 的答案,但简单地说:awaitTask<T> 展开为 TasyncT 包裹回Task<T>.

标签: c# windows-runtime async-await


【解决方案1】:

所有async 方法都返回voidTaskTask<TResult>。 lambda 只是一个匿名方法,因此仍然适用。和这个命名方法本质上是一样的:

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

为了让它返回一个Stream,它需要是一个阻塞方法,而不是一个异步方法:

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

你可能不想要那个。

如果对您有帮助,您可以使用 Task.WhenAll 将您的 IEnumerable&lt;Task&lt;Stream&gt;&gt; 转换为 Task&lt;Stream[]&gt;

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

【讨论】:

  • 或者,更好的是,使封闭方法异步并使用var streams = files.Select(await f.OpenStreamForWriteAsync());。需要 async 修饰符的不是 lambda。
【解决方案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(); }));

【讨论】:

    猜你喜欢
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2017-10-10
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多