Explore the Async and Await analysis of c,
Reading Directory: Basic Introduction
Async and Await are newly added asynchronous programming methods for net4.x. The objective of Async and Await is to simplify asynchronous programming. The following is a simple comparison with the previous APM method.
In APM mode, BeginGetRequestStream needs to pass in the callback function. When the thread encounters BeginXXX, it will continue to execute the following logic in non-blocking form. After the execution, it calls back the previously passed-in function.
HttpWebRequest myReq =(HttpWebRequest)WebRequest.Create("http://cnblogs.com/"); myReq.BeginGetRequestStream(); //to do
Async: Use Async to mark Async1 as an Asynchronous Method, and use Await to mark GetRequestStreamAsync to indicate time-consuming operations in the method. When the main thread encounters await, it will return immediately and continue to execute the logic below the main thread in non-blocking form. When await completes the time-consuming operation, continue to execute the logic below Async1
static async void Async1() { HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("http://cnblogs.com/"); await myReq.GetRequestStreamAsync(); //to do }
The above is the asynchronous Implementation of the net class library, if you want to implement your own method asynchronous.
APM mode:
public delegate int MyDelegate(int x); MyDelegate mathDel = new MyDelegate((a) => { return 1; }); mathDel.BeginInvoke(1, (a) => { },null);
Async mode:
static async void Async2() { await Task.Run(() => { Thread.Sleep(500); Console.WriteLine("bbb"); }); Console.WriteLine("ccc"); } Async2(); Console.WriteLine("aaa");
The comparison shows that async/await is very concise and elegant, and requires less code, which is more in line with people's writing habits.
Because human thinking is better at understanding linear steps.
The execution steps of APM asynchronous callback are: A logic-> false C callback logic-> B logic-> true C callback logic, which can cause confusion to some extent, when a project has a large number of asynchronous callbacks, it becomes difficult to maintain them.
The addition of Async and Await makes the original chaotic steps Correct again, and the execution steps are: A logic-> B logic-> C logic.
Basic Principle Analysis
As a programmer's self-cultivation, curiosity is very important. When Async came out, it would make people feel confused. How can await be returned directly? How can Microsoft develop a new asynchronous model. This is because we are used to the non-linear method of APM, but it is hard to understand it now. When learning Async, you can use the existing APM method to understand it,The following code is purely fictitious..
For example, imagine the Async3 method of the APM method using the Async2 method:
Static async void Async3 () {var task = await Task. run () => {Thread. sleep (1, 500); Console. writeLine ("bbb") ;}); // call back the task after the task is registered. registerCompletedCallBack () => {Console. writeLine ("ccc ");});}
I can see it above for better understanding, and then imagine the Async3 method Async4 method:
Static void Async4 () {var thread = new Thread () => {Thread. sleep (1, 500); Console. writeLine ("bbb") ;}); // callback after the thread is registered. registerCompletedCallBack () => {Console. writeLine ("ccc") ;}); thread. start ();}
This looks very simple and clear, and even async is removed, becoming familiar with programming habits. Although the Code is purely fictitious, the basic idea is the same, and the difference lies in the implementation details.
Internal Implementation Analysis
As a programmer's self-cultivation, rigor is indispensable. Although the above basic idea is easy to understand, but the specific details, programming is not a bit false work, that fictitious code can not be at all look at the officers.
Continue to read the Async2 method. The complete code after decompilation is as follows:
Internal class Program {// Methods [AsyncStateMachine (typeof (<Async2> d _ 2), DebuggerStepThrough] private static void Async2 () {<Async2> d _ 2 d __; d __. <> t _ builder = AsyncVoidMethodBuilder. create (); d __. <> 1 _ state =-1; d __. <> t _ builder. start <Async2> d _ 2> (ref d _);} private static void Main (string [] args) {Async2 (); Console. writeLine ("aaa"); Console. readLine ();} // Nested Types [CompilerGenerated] private struct <Async2> d _ 2: IAsyncStateMachine {// Fields public int <> 1 _ state; public AsyncVoidMethodBuilder <> t _ builder; private object <> t _ stack; private TaskAwaiter <> u __$ awaiter3; // Methods private void MoveNext () {try {TaskAwaiter awaiter; bool flag = true; switch (this. <> 1 _ state) {case-3: goto Label_00C5; case 0: break; default: if (Program. CS $ <> 9 _ CachedAnonymousMethodDelegate1 = null) {Program. CS $ <> 9 _ CachedAnonymousMethodDelegate1 = new Action (Program. <Async2> B _ 0);} awaiter = Task. run (Program. CS $ <> 9 _ CachedAnonymousMethodDelegate1 ). getAwaiter (); if (awaiter. isCompleted) {goto Label_0090;} this. <> 1 _ state = 0; this. <> u __$ awaiter3 = awaiter; this. <> t _ builder. awaitUnsafeOnCompleted <TaskAwaiter, Program. <Async2> d _ 2> (ref awaiter, ref this); flag = false; return;} awaiter = this. <> u __$ awaiter3; this. <> u __$ awaiter3 = new TaskAwaiter (); this. <> 1 _ state =-1; Label_0090: awaiter. getResult (); awaiter = new TaskAwaiter (); Console. writeLine ("ccc");} catch (Exception exception) {this. <> 1 _ state =-2; this. <> t _ builder. setException (exception); return;} Label_00C5: this. <> 1 _ state =-2; this. <> t _ builder. setResult ();} [DebuggerHidden] private void SetStateMachine (IAsyncStateMachine param0) {this. <> t _ builder. setStateMachine (param0) ;}} public delegate int MyDelegate (int x);} Collapse MethodsView Code
It was found that async and await were missing. It was originally a syntactic sugar optimization provided by the compiler level, so async is not a brand new asynchronous model. It can be understood that async is more of a regression of linear execution steps, specifically designed to simplify asynchronous code writing.
The decompiled Code shows that the compiler generates a new state machine structure asyncd that inherits IAsyncStateMachine (<Async2> d _ 2 in the code, which is abbreviated as AsyncD ),The following is an analysis based on the decompiled code..
The most basic State Machine Interface Definition of IAsyncStateMachine:
public interface IAsyncStateMachine{ void MoveNext(); void SetStateMachine(IAsyncStateMachine stateMachine);}
Since there is no obstacle to async and await syntax sugar, you can understand the Code Execution Process in a linear order. The entire execution process is as follows:
1. The main thread calls the Async2 () method.
2. The state of the initialization state machine in Async2 () method is-1, and AsyncD is started.
3. Execute the MoveNext method internally. The task. run function throws the task into the thread pool and returns a waiting task handle. MoveNext source code analysis:
// Delegate the task to be executed
Program.CS$<>9__CachedAnonymousMethodDelegate1 = new Action(Program.<Async2>b__0);
// Start to use tasks for Asynchronization. net4.0 is a task-based programming method.
awaiter =Task.Run(Program.CS$<>9__CachedAnonymousMethodDelegate1).GetAwaiter();
// Set the status to 0 so that MoveNext can directly break and execute the logic behind the switch, a typical state machine mode.
this.<>1__state = 0;
// Return the thread that calls the async2 method, so that it can continue to execute the logic behind the main thread
this.<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter, Program.<Async2>d__2>(ref awaiter, ref this);return;
4. Now two threads are running, namely the main thread and Task. Run.
5. Output aaa logic after the execution of the main thread, bbb output after the task thread is completed, and ccc output after the execution of the business logic after the task thread is continued.
Label_0090: awaiter.GetResult(); awaiter = new TaskAwaiter();Console.WriteLine("ccc");
It can be understood that async splits the entire main thread synchronization logic into two parts. The first part is directly executed in the main thread, the second is executed after the task thread is completed, and the second is running in the middle of the task thread. The source code is awaiter. getResult () is to execute the second block after the task thread is completed.
From the user's perspective, the execution steps are: main thread A logic-> asynchronous task thread B logic-> main thread C logic.
Test (); Console. writeLine ("A logic"); static async void Test () {await Task. run () => {Thread. sleep (1, 1000); Console. writeLine ("B logic") ;}); Console. writeLine ("C logic ");}
Looking back and comparing the fictitious method Async4 () in the Basic Principle Analysis Section, we find that the difference is that one is callback after completion, and the other is execution after completion, this is also the most basic way to implement Asynchronization.
Note: main thread A logic> asynchronous task thread B logic> main thread C logic.
Note:The three steps may use the same thread, or two or even three threads. You can test it with Thread. CurrentThread. ManagedThreadId.
Async7(); Console.WriteLine(Thread.CurrentThread.ManagedThreadId); static async void Async7() { await Task.Run(() => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); }); Console.WriteLine(Thread.CurrentThread.ManagedThreadId); }
It is because of this that some comments say that Async does not need to open a thread, or that it needs to open a thread. In a single aspect, it is both right and wrong. The above source code is analyzed in a concise manner. The specific async involves thread context switching, thread reuse, scheduling, and so on. For more information, see ExecutionContextSwitcher, SecurityContext. RestoreCurrentWI, and ExecutionContext.
In fact, you don't need to worry too much about the details of the physical thread. You just need to know the basic principle of [main thread A logic-> asynchronous task thread B logic-> main thread C logic. In addition, Async also has thread overhead, so it should be reasonably used in different business scenarios.
Summary
From the gradual Analysis of Async, it is found that the asynchronous mode provided by Net is basically the same, for example:
1. In the Async of net4.5, the throwing syntactic sugar is the Task + state machine of Net4.0.
2. For net4.0 tasks, degradation to 3.5 is (Thread, ThreadPool) + Implementation of wait, cancel, and other API operations.
Starting from async, This article briefly analyzes its internal principles and implementation, hoping to help you.