Await and async more understanding, awaitasync more

Source: Internet
Author: User

Await and async more understanding, awaitasync more

Recently, many netizens mentioned the syntactic sugar introduced by await and async, Haha and C #5.

This syntactic sugar is really not good. It can be used by a bunch of beginners. There are also a lot of online debates about this knowledge point, right or wrong, I will explain this misunderstanding here today.

In await (C # reference), write:

“awaitThe operator is applied to tasks in asynchronous methods, and the start point is inserted in the execution of the method until the waiting task is completed. A task indicates a job in progress ."


Don't underestimate these two sentences. There are actually a lot of meanings in the content.

1) await operator for asynchronous Methods

2) await insertion start point

3) await waits for the task to be completed

4) Work in progress as a task table

With the above four points, we will temporarily stop, because await cannot help but think of a good friend.Aysnc

In await (C # reference), write:

"awaitIt can only be used in asynchronous Methods Modified by the async keyword"


Here, we have questions about the four key points above.

The await operator is intended for asynchronous methods. What if we add an inbound synchronous method to the asynchronous method?

Private static async Task <TResult> XAsync () {X (); // return await XXAsync (); // XXAsync () Asynchronous Method}

 

Then, call the XAsync () method in the mainTest main thread.

static void Main(string[] args){   XAsync();

OtherMethod();}

 

 

In the main method, some online blogs said:

 

1) XAsync is not called in the main thread until awiat XAsync is called successfully. Just like a linq to SQL expression, the first is var results = array. select (). where (); statement. They are just assembled,
It will not be executed. You need to wait until the foreach (var result in results) {...} iteration or. toList () before the real query.

2) XAsync will be called in the main thread and will not stop the main thread. The main thread will continue to execute the following program! The reason is that when we write this method, vs will give us a warning.

Who is correct?

The two statements are incorrect.

First of all, XAsync () is called directly in the main thread and must be executed. VS is also confused at this time, warning us that "don't wait for this method" is a big premise!That is, the method body must be asynchronous!
It may be hard to understand.

In the XAsync () method, there is a synchronization method X (). At this time, it is a synchronization method running on the main thread and will block the main thread. After X () is fully run, the main thread call permission is returned to the called method only when return await XXAsync () is run.

In this process, no new threads are generated and all run on the main thread.

Well, the more you say, the more confused you are...

Await and async are white points. They will not actually generate new threads. We all know that the production Thread can use the Task class or Thread class.
So what is the async annotation method? Microsoft gave us a simple sentence ,"awaitIt can only be used in asynchronous Methods Modified by the async keyword"

This indicates that async plays a "Cooperative" role for await. It means that the async modification methods are asynchronous, And that is too similar.

In the synchronization method, execute the async-modified method and follow the synchronization method. That is to say, X () is the method running on the main thread.

As for the X () method, synchronous or asynchronous operations are performed in the body.,Determines whether the method in the method body has an asynchronous function!
Just as above, X () in the XAsync () method is synchronized, So X () still executes the same synchronization method, rather than running another thread.

So the question is, how good is the direct X () method and how is await used? Or why does await not directly call the X () method ?...

So let's continue to look at the next XXAsync () method. Since we use the await syntax, why does it work? Can I take him to await?

Of course, it is certain, just like this:

Private static async Task <TResult> XAsync () {X (); // X () synchronous method 0 XXAsync (); // "Asynchronous Method 1" return await XXXAsync (); // XXAsync () Asynchronous Method 2}


How does XXAsync () run at this time? Synchronous or asynchronous? The problem is returned again. synchronization or Asynchronization is not determined by the "term" of this method, but by how the method is executed in the body.

For example:


 private static async Task XXAsync()  {       X();    }

 

Now, like the method called above, XXAsync () is our usual synchronization method!

But change it to the following:

private static async Task XXAsync()  {       Task.Run(() =>{             X();         });  }


Call XXAsync in the same way. At this time, it will actually run on another "task" and it will run on other threads!

We have nothing to do with await.

So what is the difference between await before XXAsync?

The first thing to clarify here is:It does not matter whether await and XXAsync () are asynchronous or synchronous!

The real purpose of await is only to suspend this method when the Asynchronous Method XXAsync () is called. It considers this method to be a time-consuming method, the main thread or the thread that calls this method should not wait for this method.
At the same time, the code or method under the asynchronous method marked by await cannot be run because the current thread stops running, you must wait for this method to complete!


For example:
private static async Task XAsync()  {                await  XXAsync();     OtherMothod();   }

 

When running to await XXAsync (), the method called XAsync () will not run and will be returned directly, just like the return statement in our program code. The advantage of doing so is that the calling thread will not wait for this time-consuming thread. Directly let the calling thread run down,

If the call thread keeps await chain up, like the return in the method set method, it will return up layer by layer and always return to the main thread.

Each "sub-thread" waits for time-consuming I/O processing, such as database operations and network stream operations. I/O processing is particularly emphasized here, it may take some time for our program to query a database. The query command may already be running in the SQL database,

What if the database is on another remote machine? Our "sub-thread or task" is just waiting, and the main thread may have completed at this time.

How can we understand that the main thread has been completed? The mechanism of Asp.net Mvc is here. We all know that the thread pool in IIS is limited. Every Client request will go to the thread pool to get an idle thread, if the main thread is "occupying" the thread pool,

Soon the thread pool will be used up. At this time, we usually say that the "throughput" level is closely related to this! After the thread pool is requested, a new Client request is sent again, waiting for the thread pool to be released.

Mvc references the Asynchronous Method mechanism in the controller. The principle is to let time-consuming threads directly return and hand it over to the main thread, so that the main thread will immediately release the occupation of the thread pool, when the time-consuming sub-thread is completed, it will mark the await from continuing to run,

From this we can see that the asynchronous Mvc will greatly increase the "throughput" of the application.

As for the specific mvc asynchronous programming mechanism and principle, you can refer to the source code of mvc on the Internet. Here, I will just briefly describe the role of await marking in this article.



Turning back the topic:

So when will we use await to call asynchronous methods as a "mark?

Let's take a look at microsoft's classic example.

// Three things to note in the signature:  //  - The method has an async modifier.   //  - The return type is Task or Task<T>. (See "Return Types" section.)  //    Here, it is Task<int> because the return statement returns an integer.  //  - The method name ends in "Async."  async Task<int> AccessTheWebAsync()  {       // You need to add a reference to System.Net.Http to declare client.      HttpClient client = new HttpClient();      // GetStringAsync returns a Task<string>. That means that when you await the      // task you'll get a string (urlContents).      Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");  1)    // You can do work here that doesn't rely on the string from GetStringAsync.      DoIndependentWork();  2)    // The await operator suspends AccessTheWebAsync.      //  - AccessTheWebAsync can't continue until getStringTask is complete.      //  - Meanwhile, control returns to the caller of AccessTheWebAsync.      //  - Control resumes here when getStringTask is complete.       //  - The await operator then retrieves the string result from getStringTask.      string urlContents = await getStringTask;  3)    // The return statement specifies an integer result.      // Any methods that are awaiting AccessTheWebAsync retrieve the length value.      return urlContents.Length;  }  

The above example is marked with 1), 2), and 3) Red,

1) define a network flow operation and think this method may be time consuming, if you add an await client. GetStringAsync ("http://msdn.microsoft.com ")

For a program, this is an asynchronous operation that opens up a new thread, and the program returns it to the called thread or UI here, when the network stream returns to the end, it continues to wake up the called thread or main thread, and continues to run other methods.
For a website like this, a level-1 upward await will not cause any reduction in throughput or response speed, but a new problem arises. Next 2)
The DoIndependentWork () method must wait until 1) to continue running. "jump out and stand at a higher point" Does this mean "synchronization? Step by step, sub-thread shutdown does not give us too many advantages.

Yes, indeed.

We know that it is right to let the "sub-thread or task" do things and the main thread continue his work. So in 1), await should not be used, let the "thread or task run for a while".
Since we didn't add await, the main thread or the call thread and the subthread that calls the network stream "run one piece.

When the program runs until 3), 1) the task at the mark may have been completed or is about to be completed. At this time, there is only one await purpose. The following sentence is urlContents. to use Asynchronous results for Length, you must wait until the end and return a flag to the calling thread or main thread at the same time,

In order to make the caller the fastest response, rather than waiting to block.

Looking back, we need to execute our program with multiple threads or tasks to execute time-consuming tasks and quickly respond to the caller, whether or not the task has been completed! This is the real purpose.

Think about the call of DoIndependentWork () without await, and the method must be executed. It also has nothing to do with asynchronous or synchronous method, you just need to mark it.

The reason we have explained above is to add or not to the mark. Forget it. Let's take a look at it.

Let's take a look at the following questions:

How can I execute multiple await statements in a method?

We can follow the above conjecture that await sometimes functions like return, multiple await, required, the first awiat will return and Mark, any subsequent code will have to wait, for example:


private static async TaskXAsync()  {               await  XXAsync();    await  XXXAsync();   }

 

This is indeed the case. XXXAsync () must wait until the execution of the XXAsync () method ends! This will not affect the response speed of the caller, but will affect the execution efficiency of our code, which is slightly different from the two common step methods.

For example
private static async TaskXAsync()  {               XX();    XXX();   }
As in the preceding example, the XX () and XXX () Synchronization Methods are executed in sequence, and the caller cannot obtain the call permission, that is, they cannot respond in time, it must end until both methods are complete.

"Secretly", I want to add an await before the XX () and XXX () methods?

Let's look back and think about it, as mentioned above:"awaitIt can only be used in asynchronous Methods Modified by the async keyword"

In fact, when we add await to VS, an error will be reported, but the compilation will fail! Hope is shattered... Now we can see the purpose of being modified by async. Because XX () and XXX () are not modified.

Well, we will force it to be used in the synchronization method.Async!

XX(){    code here...}

 

In fact, when we add Async to the XX () method, VS prompts the following:

 

Obviously, it is impossible for the synchronous method to increase the response speed of the caller simplyAsync can be done! The root cause is that the caller and the execution method are in the same thread.

 

 

Let's go back and continue with the above example.

 

private static async TaskXAsync()  {               await  XXAsync();    await  XXXAsync();   }

It is clear above that these two statements are executed only in order and cannot be executed in parallel, which will inevitably affect the execution efficiency. How can they be executed in parallel?
Microsoft has a special method for Task. WhenAll (Tasks). Let's take a look at microsoft's example:

await SumPageSizesAsync();
 private async Task SumPageSizesAsync()        {            // Make a list of web addresses.            List<string> urlList = SetUpURLList();            // Declare an HttpClient object and increase the buffer size. The            // default buffer size is 65,536.            HttpClient client = new HttpClient() { MaxResponseContentBufferSize = 1000000 };            // Create a query.            IEnumerable<Task<int>> downloadTasksQuery =                 from url in urlList select ProcessURL(url, client);            // Use ToArray to execute the query and start the download tasks.            Task<int>[] downloadTasks = downloadTasksQuery.ToArray();            // You can do other work here before awaiting.            // Await the completion of all the running tasks.            int[] lengths = await Task.WhenAll(downloadTasks);            //// The previous line is equivalent to the following two statements.            //Task<int[]> whenAllTask = Task.WhenAll(downloadTasks);            //int[] lengths = await whenAllTask;            int total = lengths.Sum();            //var total = 0;            //foreach (var url in urlList)            //{            //    // GetByteArrayAsync returns a Task<T>. At completion, the task            //    // produces a byte array.            //    byte[] urlContent = await client.GetByteArrayAsync(url);            //    // The previous line abbreviates the following two assignment            //    // statements.            //    Task<byte[]> getContentTask = client.GetByteArrayAsync(url);            //    byte[] urlContent = await getContentTask;            //    DisplayResults(url, urlContent);            //    // Update the total.            //    total += urlContent.Length;            //}            // Display the total count for all of the web addresses.            resultsTextBox.Text +=                string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);        }

 

// The actions from the foreach loop are moved to this async method.        async Task<int> ProcessURL(string url, HttpClient client)        {            byte[] byteArray = await client.GetByteArrayAsync(url);            DisplayResults(url, byteArray);            return byteArray.Length;        }

 

  private List<string> SetUpURLList()        {            List<string> urls = new List<string>             {                 "http://msdn.microsoft.com",                "http://msdn.microsoft.com/en-us/library/hh290136.aspx",                "http://msdn.microsoft.com/en-us/library/ee256749.aspx",                "http://msdn.microsoft.com/en-us/library/hh290138.aspx",                "http://msdn.microsoft.com/en-us/library/hh290140.aspx",                "http://msdn.microsoft.com/en-us/library/dd470362.aspx",                "http://msdn.microsoft.com/en-us/library/aa578028.aspx",                "http://msdn.microsoft.com/en-us/library/ms404677.aspx",                "http://msdn.microsoft.com/en-us/library/ff730837.aspx"            };            return urls;        }

 

The example above is simple. Combine task Tasks and send themAwait Task. WhenAll (Tasks)In this way, multiple await instances are executed in parallel.

 

From the above example, we can see that each nested method is upgraded to await layer by layer. This is the await chain, not only to mark when the sub-thread completes, at the same time, the "wake up" method achieves a rapid response to the call thread and returns an upstream response layer by layer. The result is only one, so that the caller at the outermost layer can respond in a timely manner without waiting, just like the MVC principle, increase "throughput ".

However, there is a method in the middle, which does not go up to await. The caller still determines whether the method is synchronous or asynchronous Based on the execution method. If there is a returned value, the caller cannot obtain the returned value, because we cannot know whether the method has been completed, you may still need to call await in a future code segment.



Conclusion: await and async do not determine whether the method is synchronous or asynchronous, but whether the Asynchronous Method is actually executed depends on Task, asynchronous delegation, or other methods. The main function of await is,
The time-consuming Asynchronous Method for hanging up is used to send control to the caller in a timely manner. When the caller completes the task, the caller can wake up and continue to execute other methods.
The content of this section, some examples only play a role in illustration and are originally verified by practice. Due to the rush of time, no complete case is provided.
At the same time, the content of this section is mainly described in a simple language, hoping to clarify the principles for readers. If You Want To Know await and async more clearly, you can view the source code.


For more information about Asynchronization, see:

Big talk asynchronous and parallel (1) big talk asynchronous and parallel (2) big talk asynchronous and parallel (3)

 

Some examples in this Article refer

Await (C # reference) Https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/await

 

Asynchronous Programming Using Async and Await (C #) Https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index

 

Task. WhenAll method (IEnumerable <Task>) Https://msdn.microsoft.com/zh-cn/library/windows/apps/hh160384 (v = vs.110)

 

 

 

Author: Google's (Google's blog)
Source: http://www.cnblogs.com/laogu2/ welcome to reprint, but any reprint must retain the complete article, in the display of the title and the original link. If you have any questions or authorization negotiation, please leave a message for me.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.