Best practice - warning: method lacks 'await' operator warning

↘锁芯ラ 提交于 2021-02-04 19:12:51

问题


Yes, I know there are other questions to cover what this warning means and how to solve it, however, I have a question about best practices regarding async programming.

I have a service layer which handles data transfer between the data layer and the presentation layer. This service contains several methods which query the database, and return the result.

I have been trying to use async programming wherever possible. An example:

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

My problem with this is, I'm not actually awaiting anything, other than to the ToArrayAsync call, which I don't really need.

Should I go ahead and use async/await for this? And how would I for example await anything for this function:

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

I don't await anything in that function, but I also don't need to call ToArrayAsync, so how do I avoid the warning "method lacks 'await' operator" in above case?

Thanks in advance.


回答1:


If you have nothing to await in a method that needs to be async (for whatever reason), you can use Task.FromResult, which can be awaited:

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

If you don't need the async method, you can simply more the async Task<int> and replace it for int.




回答2:


Asynchornous api does not necessary need async\await keywords. First you should ask yourself if anything you call inside your method use IO and have asynchronous version of that IO api. In your case you try to access database, that is IO, your library has asynchronous version (ToArrayAsync), so all makes sense. Now check if you do anything else after calling that asynchronous api. If yes - use async\await. If not - just return the result back to the caller:

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

In the second case you also try to access database, but you think that there is no async api to do that. Most likely that is not true, because if you have ToArrayAsync - it's very likely all database access methods have async version and so you should have FirstAsync. Then your method becomes:

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

Here you do something after calling FirstAsync, so you need to use async\await keywords.




回答3:


async/await are needed only if you want to process the results of an already asynchronous operation in the method itself. They don't make the method or the call asynchronous. If you don't need to process the Task result, you can just return it:

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

or, using an expression bodied method

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

You can avoid async/await in the second case as well and still keep it asynchronous, if you use Where,Select and FirstAsync:

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

This has the added advantage of returning only the ID from the database. If you didn't use Select, the provider would have to read the entire object




回答4:


Maybe you can change your code like bellow:

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

Have a nice day!



来源:https://stackoverflow.com/questions/43996056/best-practice-warning-method-lacks-await-operator-warning

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!