In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces "how to understand Await and Async". In daily operation, I believe many people have doubts about how to understand Await and Async. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts about "how to understand Await and Async"! Next, please follow the editor to study!
One: background
1. Tell a story
The knowledge of await,async is so bad that it doesn't seem to have much to say, but I find that there are many articles about the use of these two grammatical sugars in theory. I still know it or understand it, and I don't seem to understand it after a few days. Life is like a play that depends on memorization. In fact, in essence, await,async is only grammatical sugar at the compiler level, and it will be prototyped at the IL level. Therefore, it is very necessary to know these two grammatical sugars at this level.
Second: understanding from the level of IL
1. Download using WebClient
In order to make it easier to return to the prototype, let me start with a previous example and download http://cnblogs.com 's html asynchronously using webclient, as follows:
Class Program {static void Main (string [] args) {var html = GetResult (); Console.WriteLine ("hold on. Downloading cnblogs-> html\ r\ n "); var content = html.Result; Console.WriteLine (content);} static async Task GetResult () {var client = new WebClient (); var content = await client.DownloadStringTaskAsync (" http://cnblogs.com")); return content;}})
The above code is very simple. You can see that the asynchronous operation does not block the output of the main thread: wait a minute. Downloading cnblogs-> html\ r\ nThere is nothing to say at the compiler level, so let's take a look at what happens at the IL level.
two。 Mining the IL code of await async
As usual, ilSpy starts walking, as shown in the following figure:
As you can see, there is a GetResult method, a Main method, and a dumbbell class that pops up out of nowhere. Let's talk to you one by one.
\ dcards 1 > class
Because it comes out of nowhere, it attracts people's attention, so what does its IL look like?
.class nested private auto ansi sealed beforefieldinit'method private final hidebysig newslot virtual instance void SetStateMachine 1' extends [System.Runtime] System.Object implements [System.Runtime] System.Runtime.CompilerServices.IAsyncStateMachine {.method private final hidebysig newslot virtual instance void MoveNext () cil managed {} .method private final hidebysig newslot virtual instance void SetStateMachine (class [System.Runtime] System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) cil managed {}}
As you can see from the IL code above, this is an automatically generated dumped class 1 that implements the interface IAsyncStateMachine, defined as follows:
See inside the MoveNext is not very familiar, usually you in the foreach collection will use this method, at that time people called enumeration class, here is modified, called state machine?
GetResult ()
To make it easier to demonstrate, I simplified the IL code in the body of the other method:
.method private hidebysig static class [System.Runtime] System.Threading.Tasks.Task`1 GetResult () cil managed {IL_0000: newobj instance void ConsoleApp3.Program/'d__1'::.ctor () IL_0005: ldloc.0 IL_0007: call valuetype [System.Threading.Tasks] System.Runtime.CompilerServices.AsyncTaskMethodBuilder `1 valuetype [System.Threading.Tasks] System.Runtime.CompilerServices.AsyncTaskMethodB uilder`1:: Create () IL_000c: stfld valuetype [System.Threading.Tasks] System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 ConsoleApp3.Program/'d__1'::'t__builder' IL_0011: ldloc.0 IL_0012: ldc.i4.m1 IL_0013: stfld int32 ConsoleApp3.Program/'d__1'::'1__state' IL_0018: ldloc.0 IL_0019: ldflda valuetype [System.Threading.Tasks] System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 ConsoleApp3.Program/'d__1': : 'taper builder' IL_001e: ldloca.s 0 IL_0020: call instance void valuetype [System.Threading.Tasks] System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:: Start (! 0 &) IL_0025: ldloc.0 IL_0026: ldflda valuetype [System.Threading.Tasks] System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 ConsoleApp3.Program/'d__1'::'t__builder' IL_002b: call instance class [System.Runtime] System.Threading.Tasks.Task`1 Valuetype [System.Threading.Tasks] system. Runtime.CompilerServices.AsyncTaskMethodBuilder`1:: get_Task () IL_0030: ret} / / end of method Program::GetResult
If you understand a little bit, in the newobj at IL_0000, you should know that this method is to do a newd__1, and then return a get_Task () from IL_002b, then you should understand why the main thread will not be blocked, because people return Task, right, the final http result will be hidden in the Task, so it is easy to understand.
Main
The Main method hasn't changed anything, just what it used to be or what it is now.
Three: write back the IL code to C #
1. Complete C # code
Through the previous section you should have a framework understanding of await and async at the IL level, here I will reverse it all into C # code:
Class Program {static void Main (string [] args) {var html = GetResult (); Console.WriteLine ("hold on. Downloading cnblogs-> html\ r\ n "); var content = html.Result; Console.WriteLine (content);} static Task GetResult () {GetResult stateMachine = new GetResult (); stateMachine.builder = AsyncTaskMethodBuilder.Create (); stateMachine.state =-1; stateMachine.builder.Start (ref stateMachine) Return stateMachine.builder.Task;}} class GetResult: IAsyncStateMachine {public int state; public AsyncTaskMethodBuilder builder; private WebClient client; private string content; private string S3; private TaskAwaiter awaiter; public void MoveNext () {var result = string.Empty; TaskAwaiter localAwaiter; GetResult stateMachine Int num = state; try {if (num = = 0) {localAwaiter = awaiter; awaiter = default (TaskAwaiter); num = state =-1 } else {client = new WebClient (); localAwaiter = client.DownloadStringTaskAsync (new Uri ("http://cnblogs.com")).GetAwaiter(); if (! localAwaiter.IsCompleted) {num = state = 0) Awaiter = localAwaiter; stateMachine = this; builder.AwaitUnsafeOnCompleted (ref localAwaiter, ref stateMachine); return;}} S3 = localAwaiter.GetResult (); content = S3; S3 = null Result = content;} catch (Exception exx) {state =-2; client = null; content = null; builder.SetException (exx);} state =-2; client = null; content = null Builder.SetResult (result);} public void SetStateMachine (IAsyncStateMachine stateMachine) {}}
As you can see, there is no problem with running after writing back into C # code. In order to make it easier to understand, I will draw a flow chart first.
Through the above xmind, its basic flow is as follows: stateMachine.builder.Start (ref stateMachine)-> GetResult.MoveNext-> client.DownloadStringTaskAsync-> localAwaiter.IsCompleted = false-> builder.AwaitUnsafeOnCompleted (ref localAwaiter, ref stateMachine)-> GetResult.MoveNext-> localAwaiter.GetResult ()-> builder.SetResult (result)
two。 Dissecting AsyncTaskMethodBuilder
In fact, you will find that the so-called asynchronization of await,async is carried by AsyncTaskMethodBuilder, such as the start of asynchronous tasks, the marshaling of html results, and contact with the underlying IO, where Task corresponds to AsyncTaskMethodBuilder and Task corresponds to AsyncTaskMethodBuilder, which is why the compiler keeps prompting you to return Task and Task at async. If you don't, you can't find the corresponding AsyncTaskMethodBuilder, right?
Then focus on the AwaitUnsafeOnCompleted method, which is very important and is annotated as follows:
/ Summary: / / Schedules the state machine to proceed to the next action when the specified / / awaiter completes. This method can be called from partially trusted code. Public void AwaitUnsafeOnCompleted (ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter: ICriticalNotifyCompletion where TStateMachine: IAsyncStateMachine
Once this method is called, you need to wait for the underlying IO to call back GetResult.MoveNext twice after the task is processed, which means either the exception or the task is completed, and the Task result wrapped by Awaiter is marshaled to builder.SetResult.
Then briefly talk about the way the state machine goes, through debugging, you will find that there will be two MoveNext, one to start, one to get the results.
MoveNext callback for the first time
The trigger of the first MoveNext is initiated by stateMachine.builder.Start (ref stateMachine). You can debug it with dnspy, as shown below:
The second callback MoveNext
The trigger of the second MoveNext starts with builder.AwaitUnsafeOnCompleted (ref localAwaiter, ref stateMachine). You can see that once the network driver is processed, the thread pool IO thread initiates actively to the MoveNext in the final trigger code, and finally ends at the result where the task is obtained in the awaiter, as shown below:
At this point, the study on "how to understand Await and Async" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.