【问题标题】:Best practice - warning: method lacks 'await' operator warning最佳实践 - 警告:方法缺少“等待”操作员警告
【发布时间】:2017-10-15 05:11:33
【问题描述】:

是的,我知道还有其他问题可以涵盖此警告的含义以及如何解决它,但是,我有一个关于异步编程最佳实践的问题。

我有一个服务层,它处理数据层和表示层之间的数据传输。该服务包含多个查询数据库并返回结果的方法。

我一直在尝试尽可能使用异步编程。一个例子:

    public async Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)
    {
        return await Database.FindBy<SiteTemplateResource>(str => str.SiteTemplateId == siteTemplateId && str.HashedFile.EndsWith(extension)).ToArrayAsync();
    }

我的问题是,除了ToArrayAsync 电话之外,我实际上并没有等待任何东西,我真的需要它。

我应该继续使用 async/await 吗?例如,我将如何等待此功能的任何内容:

    public async Task<int> SiteTemplateBySiteIdAsync(int siteId)
    {
        return Database.First<SiteSiteTemplate>(sst => sst.SiteId == siteId).SiteTemplateId;
    }

我不等待该函数中的任何内容,但我也不需要调用ToArrayAsync,那么在上述情况下如何避免警告“方法缺少'await'运算符”?

提前致谢。

【问题讨论】:

  • 如果你有ToArrayAsync,你也应该有FirstAsync。至于第一种方法 - 只需删除 async\await 关键字。 ToArrayAsync 返回 Task 并且您的 GetResources 方法返回 Task - 此处无需使用 async\await。
  • @Evk 我不知道它存在,谢谢。
  • 如果返回异步操作的结果,则不需要使用async/await。只需使用public Task&lt;...&gt; GetResources(..)=&gt; return Database.FindBy.....ToArrayAsync();
  • 你也可以使用WhereSelectFirstAsync来保持第二种方法异步

标签: c# async-await


【解决方案1】:

如果你对await没有什么需要async的方法(无论出于何种原因),你可以使用Task.FromResult,可以等待:

public async Task<int> SiteTemplateBySiteIdAsync(int siteId)
{
    return await Task.FromResult(Database.First<SiteSiteTemplate>(sst => sst.SiteId == siteId).SiteTemplateId);
}

如果您不需要 async 方法,您可以简单地将 async Task&lt;int&gt; 替换为 int

【讨论】:

  • 由于您立即返回,您甚至可以删除 async 和 await 关键字。只要它重新启动一个任务,一切都会好起来的。
  • 谢谢!这看起来像我需要的。当您说“需要async 的方法”时,您是否暗示并非所有内容都应该是异步的?目前我的观点是尽可能使函数异步,但这是正确的想法吗?
  • 不,不一定。有时你会绑定到接口,所以有时你需要拥有它们,即使代码本身不需要它。在不需要的时候不创建方法async 也可以。
  • 但是如果你在最低的方法中使用async,你需要一直到async
【解决方案2】:

也许您可以像下面这样更改您的代码:

public int SiteTemplateBySiteIdAsync(int siteId)
{
    return Database.First<SiteSiteTemplate>(sst => sst.SiteId == siteId).SiteTemplateId;
}

祝你有美好的一天!

【讨论】:

    【解决方案3】:

    Asynchornous api 不需要 async\await 关键字。首先,您应该问自己,您在方法中调用的任何内容是否使用 IO 并具有该 IO api 的异步版本。在您的情况下,您尝试访问数据库,即 IO,您的库具有异步版本(ToArrayAsync),所以一切都有意义。现在检查您是否在调用该异步 api 之后 做了其他任何事情。如果是 - 使用 async\await。如果不是 - 只需将结果返回给调用者:

    public Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)
    {
        return Database.FindBy<SiteTemplateResource>(str => str.SiteTemplateId == siteTemplateId && str.HashedFile.EndsWith(extension)).ToArrayAsync();
    }
    

    在第二种情况下,您也尝试访问数据库,但您认为没有异步 api 可以做到这一点。这很可能不是真的,因为如果你有ToArrayAsync - 很可能所有数据库访问方法都有异步版本,所以你应该有FirstAsync。那么你的方法就变成了:

    public async Task<int> SiteTemplateBySiteIdAsync(int siteId)
    {
        var result = await Database.FirstAsync<SiteSiteTemplate>(sst => sst.SiteId == siteId);
        return result.SiteTemplateId;
    }
    

    这里调用FirstAsync后做一些事情,所以需要使用async\await关键字。

    【讨论】:

    • 如果您使用WhereSelect,则不需要await。如果提供者只返回SiteTemplateId,查询也可能更有效。事实上,它必须返回整个对象。
    【解决方案4】:

    async/await 仅当您想在方法本身中处理已经异步操作的结果时才需要。他们不会使方法或调用异步。如果你不需要处理Task结果,你可以直接返回:

    public Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)
    {
        return Database.FindBy<SiteTemplateResource>(str => 
                               str.SiteTemplateId == siteTemplateId 
                               && str.HashedFile.EndsWith(extension))
                       .ToArrayAsync();
    }
    

    或者,使用表达式主体方法

    public Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)=>
            Database.FindBy<SiteTemplateResource>(str => 
                            str.SiteTemplateId == siteTemplateId 
                            && str.HashedFile.EndsWith(extension))
                    .ToArrayAsync();
    

    如果你使用Where,Select 和FirstAsync,你也可以在第二种情况下避免async/await,并且仍然保持异步:

    public Task<int> SiteTemplateBySiteIdAsync(int siteId)=>
        Database.Where(sst => sst.SiteId == siteId)
                .Select(it=>it.SiteTemplateId)
                .FirstAsync();
    }
    

    这具有从数据库返回 ID 的额外优势。如果您不使用Select,则提供程序必须读取整个对象

    【讨论】:

      猜你喜欢
      • 2012-10-25
      • 2021-01-24
      • 2018-11-25
      • 1970-01-01
      • 2014-08-03
      • 2017-11-08
      • 2014-02-13
      • 2015-11-20
      • 1970-01-01
      相关资源
      最近更新 更多