Where does async and await end? Confusion

大憨熊 提交于 2021-01-27 06:17:13

问题


I have a program which has no purpose but to help me understand how async and await works. It's a console application which parses XML and waits for a name to be returned, either the surname or the first name. Here is the code:

static void Main(string[] args)
{
     Task<string> name = GetFirstParsedName();
     name.Wait();
     if (name.IsCompleted)
     {
         Console.WriteLine(name.Result);
     }

     Console.ReadLine();
 }

static async Task<string> GetFirstParsedName()
{
  string xmlSnippet = @"<person>
<FirstName>Chamir</FirstName>
<Surname>Bodasing</Surname>
<Gender>Male</Gender>
<Nationality>South African</Nationality></person>";

  XmlDocument xmlDoc = new XmlDocument();
  xmlDoc.LoadXml(xmlSnippet);

  XmlParser xmlParser = new XmlParser();
  Task<string> t_GetFirstName = xmlParser.GetFirstName(xmlDoc);
  Task<string> t_GetSurname = xmlParser.GetSurname(xmlDoc);  

  Task<string> t_firstReturnedName = await Task.WhenAny(new Task<string>[] { t_GetFirstName, t_GetSurname });

  string firstReturnedName = await t_firstReturnedName;
  return firstReturnedName;    
}

static async Task<string> GetFirstName(XmlDocument personXml)
{
  string firstName = personXml.SelectSingleNode("//FirstName").InnerText;
  await Task.Delay(5000);
  return firstName;
}

static async Task<string> GetSurname(XmlDocument personXml)
{
  string surname = personXml.SelectSingleNode("//Surname").InnerText;
  await Task.Delay(1);
  return surname;
}

It seems like it only makes sense to use the async method when you don't have to return a value to a main method. Unless it means setting a global class property which can then be accessed. If not, in order to await the method, all methods need to be async which in turn means that the return type must be Task<T>. It seems like it never ends unless I explicitly have to write the following code (as in above main method):

Task<string> name = GetFirstParsedName();
name.Wait();
if (name.IsCompleted)
{
    Console.WriteLine(name.Result);
 }

Is my understanding correct at all? I have to use the result property to get the value here and from reading up about this, it seems that this is not the best practice.


回答1:


It seems like it only makes sense to use the async method when you don't have to return a value to a main method.

Why do you say that? It makes sense to use an async method where-ever you have a naturally asynchronous operation ongoing. No matter if that operation has a return value or doesn't.

in order to await the method, all methods need to be async which in turn means that the return type must be "Task" . It seems like it never ends

That's correct. Async spreads in your code like a plage, from the bottom to the top of your stack. It usually reaches the highest calling place in your stack (be it a console Main method or a UI event handler). That's the advantage of using async, it allows you to asynchronously wait an operation while freeing the calling thread. This can help, for example, if you have a WebAPI endpoint which needs to handle a large amount of requests concurrently. If you spend most of your time querying a database, you can free that calling thread in the meanwhile to serve more requests.

Is my understanding correct at all? I have to use the result property to get the value here and from reading up about this, it seems that this is not the best practice.

You have to use the Result property because a console application is a special case, where Main cant be marked as async (unless you're using ASP.NET CoreCLR console app). If this was a UI event handler or an ASP.NET action, you'd properly await the async call.




回答2:


It seems like it only makes sense to use the async method when you don't have to return a value to a main method. Unless it means setting a global class property which can then be accessed.

Your async methods can return Task<T> to return a value to its caller. Asynchronous methods do not work very well if they depend on side effects (i.e., setting properties / globals); they work much better if your code is more pure (i.e., taking parameters and returning results).

If not, in order to await the method, all methods need to be async which in turn means that the return type must be "Task" . It seems like it never ends

This is why one of the central principles of async is "async all the way". In most applications, this is exactly what you should do. Eventually, the "async chain" generally ends in an async void event handler (for UI apps) or an async Task<T> entry point (for ASP.NET apps). Console apps are unusual since they do require an explicit Wait()/Result or equivalent in their Main method.

After all, the whole point of async is to free up the calling thread. If the next method up the call stack blocks that same thread until the async code is complete, well, that was a whole lot of work for no benefit...




回答3:


Well, async keyword let's compiler know that your method is going to execute series of asynchronous calls that should most likely be awaited but should not block the main (or UI) thread.

To help you understand async-await a little bit, here is some simple example:

Consider the scenario, when user clicks 'Save' button on WinForm's app, and some UI operation is started asynchronously in different Thread.

The code is :

    private Task SomeUIOperation()
    {
        // ui operation
        return Task.Run(() =>
        {
            this.Invoke(new Action(() => this.BackColor = Color.Aquamarine));
            Thread.Sleep(10000);
            this.Invoke(new Action(() => this.BackColor = Color.Gray));
        });
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        await SomeUIOperation();

        // some other stuff
    }

If we do not use async-await here UI thread will become unresponsive for 10 seconds.

It's an example of how you usually use async-await, you use it when you want some piece of code to be executed only when asynchronous operation is completed and in the same time you do not want the main thread to be blocked.

And console application is not the best project type for testing and learning Async-Await



来源:https://stackoverflow.com/questions/33067874/where-does-async-and-await-end-confusion

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