为什么返回等待Task.FromResult(true);而不只是返回真实?

时间:2017-11-29 14:19:27

标签: c# async-await

使用VS2017创建Xamarin Forms Master-Detail示例时,您将获得使用

等方法生成的MockDataStore类
    public async Task<bool> DeleteItemAsync(string id)
    {
        var _item = items.Where((Item arg) => arg.Id == id).FirstOrDefault();
        items.Remove(_item);

        return await Task.FromResult(true);
    }

这是一个微软的例子,因此它必须是正确的。感觉很天真。

我不明白为什么这些方法不仅仅是return true而且我没有看到这个成语解释过。我是否遗漏了一些微妙的内容,或者这是一个应该从模板中清除的历史性解决方法?

3 个答案:

答案 0 :(得分:4)

我认为这背后的原因是为了防止“异步方法缺少等待运算符”编译器警告。这个自动生成的代码的作者想要标记函数async,因为这是您在实现实际功能时将要做的事情。因此,为了防止编译器警告(没有自动生成的代码应该生成编译器警告),您需要等待一些东西,并且他们的代码中没有任何东西需要等待,所以他们选择等待Task.FromResult

当然,当您自己编写代码而不是自动生成代码以供将来编辑时 - 您不需要这样做。

答案 1 :(得分:0)

这个方法可能(应该)同步实现,因为它确实是真正的同步:

public bool DeleteItem(string id)
{
    var _item = items.Where((Item arg) => arg.Id == id).FirstOrDefault();
    items.Remove(_item);

    return true;
}

将同步方法命名为* Async并返回Task<T>毫无意义。

我猜你应该在那里添加你自己的异步删除逻辑。毕竟,生成的代码只是示例代码。

然后等待实际的数据库操作而不是Task.FromResult(true),即用对执行数据库查询的方法的异步调用替换Task.FromResult(true),然后返回true一旦异步方法成功返回。

答案 2 :(得分:0)

TL; DR:当函数返回TaskTask<T>时,它将异步处理。但它本身并不需要async

使用async ... await表示编译器构建一个状态机来处理这个问题。但是,如果您等待的唯一事情是最后一个表达式,则可以避免使用此状态机:

public Task<bool> DeleteItemAsync(string id)
{
    // Nothing awaitable here...

    return Task.FromResult(true);
}

并创建一个同步运行的函数 - 但具有异步函数的签名和行为,因为它会对异步执行的操作进行调用。

为什么要返回Task<T>:因为这就是调用者所期望的:如果不更改所有呼叫者,他们的呼叫者和他们的呼叫者,......就一直向下(可能),这是无法改变的。

因此签名无法更改。你必须返回一些等待的东西。但是你可以返回另一个结果的“可靠性”,如果这是你做的最后一件事(有点像实现尾递归)。

  

你得到一个MockDataStore

所以这只是用于测试:开销不太可能很重要,并且它提供的代码可以作为真实代码看起来像的一个很好的例子。 (比非常好 - 非常差 - 脚手架代码提供了一个不好的例子。)

注意:使用C#7时,使用ValueTask<T>可以避免在立即知道结果时分配Task<T>的开销。