简体   繁体   English

如何正确使用“async”和“await”使应用程序异步?

[英]How to properly make app async with “async” and “await”?

class Website
{
    public Website(string link)
    {
        _linkToWeb = new RestClient(link);
    }
    public async Task<string> DownloadAsync(string path)
    {
        var request = new RestRequest(path, Method.GET);
        var response = _linkToWeb.ExecuteAsync(request);
        return response.Result.Content;
    }
    public RestClient _linkToWeb { get; set; }
}

class Program
{
    public static Website API = new Website("https://api.collegefootballdata.com");
    public static async Task<string> _downloadTeamsFromAPI()
    {
        return API.Download("/teams/fbs");
    }
    public static async Task<string> _downloadAdvancedInfoFromAPI()
    {
        return API.Download("/stats/season/advanced?year=2010");
    }
    public static async Task<Teams> _addTeamToDB(Teams item)
    {
        var tmp = new Teams
        {
            School = item.School,
            Abbreviation = item.Abbreviation,
            Conference = item.Conference,
            Divison = item.Divison,
            Color = item.Color,
            Alt_Color = item.Alt_Color,
            Team = await _getAdvancedInfoFromAPI(item.Conference)
        };
        return tmp;
    }
    public static async Task<string> _getAdvancedInfoFromAPI(string _conferenceName)
    {
        List<Advanced> advancedDataList = new List<Advanced>();
        var advancedData = await _downloadAdvancedInfoFromAPI();
        var advancedDataDeserialized = JsonSerializer.Deserialize<Advanced[]>(advancedData, new JsonSerializerOptions()
        {
            PropertyNameCaseInsensitive = true
        });

        foreach (var item in advancedDataDeserialized)
        {
            advancedDataList.Add(new Advanced
            {
                Team =                  item.Team,
                //Conference =            item.Conference,
                Year =                  item.Year,
                excludeGarbageTime =    item.excludeGarbageTime,
                startWeek =             item.startWeek,
                endWeek =               item.endWeek
            });
        }
        return await _lookForMatch(_conferenceName, advancedDataList);
    }
    public static async Task<string> _lookForMatch(string _Confa, List<Advanced> lista)
    {
        return lista
                        .Where(x => x.Conference == _Confa)
                        .Select(x => x.Team)
                        .FirstOrDefault();
    }
    public static async Task Main()
    {
        Console.WriteLine("Odpaliłem program!\n");
        using var db = new Context();
        db.Database.EnsureCreated();
        Console.WriteLine("Stworzylem baze!\n");
        var teams = await _downloadTeamsFromAPI();

        var deserializer = JsonSerializer.Deserialize<Teams[]>(teams, new JsonSerializerOptions()
        {
            PropertyNameCaseInsensitive = true
        });
        Console.WriteLine("Zdeserializowalem dane!\n");
        foreach (var item in deserializer)
        {
            db.Teams.Add(await _addTeamToDB(item));
            Console.WriteLine(DateTime.Now.ToString("HH:mm:ss"));
            Console.WriteLine("Dodalem element do bazy...\n");
        };
        db.SaveChanges();
        Console.WriteLine("Zapisalem dane do bazy!");
    }
} 

I know it's a noob question but I don't know how to make it work :/我知道这是一个菜鸟问题,但我不知道如何使它起作用:/

I want to make it a bit asynchronous, because the words async and await doesn't exactly make it more asynchronous, but I don't know how to make it work anyhow asynchronous.我想让它有点异步,因为asyncawait这两个词并没有让它更异步,但我不知道如何让它以任何方式异步工作。

The app first downloads the information from API, deserializes it and stores it into var type variable.该应用程序首先从 API 下载信息,对其进行反序列化并将其存储到var类型变量中。 Then it downloads the advanced info from API and joins it by "Conference" item.然后它从 API 下载高级信息并通过“会议”项加入它。 (that is on purpose, even though it's not optimal). (这是故意的,即使它不是最佳的)。

There are a lot of async s and await s but I don't think it anyhow runs asynchronously.有很多asyncawait ,但我认为它无论如何都不会异步运行。 What should I change to make this app actually async?我应该改变什么才能使这个应用程序真正异步?

I appreciate your motive to write asynchronous code to make your application more scalable.我很欣赏您编写异步代码以使您的应用程序更具可扩展性的动机。 However after going through the sample code posted, I am afraid you need to do more learning on the concepts of asynchronous programming rather than just jumping into the console and trying to write some code which looks like asynchronous code.但是,在浏览了发布的示例代码之后,恐怕您需要更多地了解异步编程的概念,而不仅仅是跳入控制台并尝试编写一些看起来像异步代码的代码。

Start slowly and try to understand the purpose of Task library, when to use it.慢慢开始,试着理解Task库的用途,什么时候用。 What await does behind the scenes. await在幕后做了什么。 When to wrap a return type with Task and when to mark a method as async .何时用Task包装返回类型以及何时将方法标记为async These are some of the main keywords which you come across in asynchronous code and a good understanding of these is a must to write/understand asynchronous code.这些是您在异步代码中遇到的一些主要关键字,很好地理解这些是编写/理解异步代码的必要条件。

There are plenty of resources available online to get a hang of these concepts.网上有很多资源可以帮助您掌握这些概念。 For starters, you can begin looking into Microsoft Documentation对于初学者,您可以开始查看Microsoft 文档

Having said that, inline is a rewrite of the sample code with proper use of async/await .话虽如此,内联是通过正确使用async/await重写示例代码。 Please use this for references purpose only.请将此仅用于参考目的。 Do not try to put into some production code until unless you have a good understanding of the concept.除非您对概念有很好的理解,否则不要尝试将其放入一些生产代码中。

Necessary comments are provided to explain some critical changes made.提供了必要的评论以解释所做的一些关键更改。

class Website
{
    public Website(string link)
    {
        _linkToWeb = new RestClient(link);
    }

    public async Task<string> DownloadAsync(string path)
    {
        var request = new RestRequest(path, Method.GET);
        var response = await _linkToWeb.ExecuteAsync(request); //await an asynchronous call.
        return response.Content; //No need to call response.Result. response content can be fetched after successful completion of asynchronous call.
    }
    public RestClient _linkToWeb { get; set; }
}

class Program
{
    public static Website API = new Website("https://api.collegefootballdata.com");

    public static async Task<string> _downloadTeamsFromAPI()
    {
        return await API.DownloadAsync("/teams/fbs");
    }

    public static async Task<string> _downloadAdvancedInfoFromAPI()
    {
        return await API.DownloadAsync("/stats/season/advanced?year=2010");
    }

    public static async Task<Teams> _addTeamToDB(Teams item)
    {
        var tmp = new Teams
        {
            School = item.School,
            Abbreviation = item.Abbreviation,
            Conference = item.Conference,
            Divison = item.Divison,
            Color = item.Color,
            Alt_Color = item.Alt_Color,
            Team = await _getAdvancedInfoFromAPI(item.Conference)
        };
        return tmp;
    }

    //Return type has to be Task<Teams> rather than Task<string> because the return object is Teams.
    public static async Task<Teams> _getAdvancedInfoFromAPI(string _conferenceName)
    {
        List<Advanced> advancedDataList = new List<Advanced>();
        var advancedData = await _downloadAdvancedInfoFromAPI();
        var advancedDataDeserialized = JsonSerializer.Deserialize<Advanced[]>(advancedData, new JsonSerializerOptions()
        {
            PropertyNameCaseInsensitive = true
        });

        foreach (var item in advancedDataDeserialized)
        {
            advancedDataList.Add(new Advanced
            {
                Team = item.Team,
                //Conference =            item.Conference,
                Year = item.Year,
                excludeGarbageTime = item.excludeGarbageTime,
                startWeek = item.startWeek,
                endWeek = item.endWeek
            });
        }
        return _lookForMatch(_conferenceName, advancedDataList);
    }

    //Return type is Teams and not string. 
    //Moreover Task<string> not required because we are not awaiting method call in this method.
    public static Teams _lookForMatch(string _Confa, List<Advanced> lista) 
    {
        return lista.Where(x => x.Conference == _Confa)
                        .Select(x => x.Team)
                        .FirstOrDefault();
    }

    public static async Task Main()
    {
        Console.WriteLine("Odpaliłem program!\n");
        using var db = new Context();
        db.Database.EnsureCreated();
        Console.WriteLine("Stworzylem baze!\n");
        var teams = await _downloadTeamsFromAPI();

        var deserializer = JsonSerializer.Deserialize<Teams[]>(teams, new JsonSerializerOptions()
        {
            PropertyNameCaseInsensitive = true
        });
        Console.WriteLine("Zdeserializowalem dane!\n");
        foreach (var item in deserializer)
        {
            db.Teams.Add(await _addTeamToDB(item));
            Console.WriteLine(DateTime.Now.ToString("HH:mm:ss"));
            Console.WriteLine("Dodalem element do bazy...\n");
        };
        db.SaveChanges();
        Console.WriteLine("Zapisalem dane do bazy!");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM