最佳实践 - 警告:方法缺乏'等待'操作员警告

时间:2017-05-16 08:21:43

标签: c# async-await

是的,我知道还有其他问题要涵盖此警告的含义以及解决方法,但是,我对异步编程的最佳做法有疑问。

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

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

    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,所以如何避免警告&#34;方法缺乏等待&#39; await& #39;操作员&#34;在上面的情况?

提前致谢。

4 个答案:

答案 0 :(得分:5)

如果某个方法中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<int>并将其替换为int

答案 1 :(得分:2)

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 \ _wait关键字。

答案 2 :(得分:1)

仅当您要在方法本身中处理已经异步操作的结果时才需要

async/await。它们不会使方法或调用异步。如果您需要处理任务结果,您只需返回它:

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

如果您使用async/await,选择并Where

,您也可以在第二种情况下避免使用FirstAsync并保持异步
public Task<int> SiteTemplateBySiteIdAsync(int siteId)=>
    Database.Where(sst => sst.SiteId == siteId)
            .Select(it=>it.SiteTemplateId)
            .FirstAsync();
}

这具有从数据库返回 ID的附加优势。如果您没有使用Select,则提供者必须阅读整个对象

答案 3 :(得分:0)

也许你可以改变你的代码如下:

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

度过美好的一天!